I don’t mean to be flippant, but you have two issues:
- Identifying the subdirectories named
dist
, and
- moving or copying them into the
Artifacts
directory.
This is quite a bit easier if we use relative pathnames.
If you absolutely need to use absolute pathnames (har har), say so.
Here are two ways to do step 1
(identifying the subdirectories named dist
):
find
#!/bin/sh
cd ~/Documents/Packages &&
find . -name dist -type d -exec sh -c 'for d do parent="${d%/*}"; \
mkdir -p "../Artifacts/$parent"; \
mv "$d" "../Artifacts/$parent"; done' \
sh {} +
(You can put the find
command all on one line if you want.)
This goes into ~/Documents/Packages
, so we can use relative pathnames.
A fairly straightforward use of the -name
and -type
tests
of find
to identify (sub)directories named dist
.
Use the -exec
action to pass their names to a miniature shell script.
The script loops over its arguments.
For each one, it identifies the parent directory
by removing /
and a pathname level from the right.
For example, the parent of ./core-types/dist
is ./core-types
.
(Remember; we are in ~/Documents/Packages
and looking at .
,
so we are seeing relative pathnames.)
I could have said parent="${d%/dist}"
, but I wanted to keep it generic.
Create the destination/parent directory —
for example, ../Artifacts/./core-types
.
(The extra ./
is ignored; /./
acts like /
,
so this creates ../Artifacts/core-types
, which is ~/Documents/Packages/../Artifacts/core-types
,
which is ~/Documents/Artifacts/core-types
.)
We then move the dist
directory into that directory.
bash Pathname Expansion
This depends on a feature of bash that is not present in all shells.
(For that matter, it might not be in all versions of bash.)
#!/bin/bash
cd ~/Documents/Packages && shopt -s globstar &&
for d in **/dist/; do d="${d%/}"; parent="${d%/*}";
mkdir -p "../Artifacts/$parent";
mv "$d" "../Artifacts/$parent"; done
Set the globstar
shell option (shopt
),
which causes **
to do a recursive search.
Then loop through **/dist/
.
If we said **/dist
,
that would find all files and directories named dist
;
adding the /
at the end constrains the search to (sub)directories only.
For each one, execute a bunch of commands.
**/dist/
gives us the directory names in the form core-types/dist/
(with the /
at the end, as we specified).
d="${d%/}"
strips off that trailing slash.
The rest of the code is the same.
Note: this will not look under top-level directories
whose names begin with .
(e.g., ~/Documents/Packages/.memories/dist
)
unless you add the dotglob
option.
Step 2
If you want to copy instead of move,
just change mv
to cp -R
in either of the above commands.
Best Answer
Obviously, you want to convert some HTML pages into plain text. Therefore I wouldn't strip the tags with a custom built solution (e.g. with some sed magic), but use a tool designed for that purpose like html2text; from its webpage:
To address your question of batch renaming:
Here the find command lists all directories only located in the current directory (i.e. not recursive) and the read command (in the while condition) assigns the values to the variable
$dirname
. Finally, the command(s) betweendo
anddone
get(s) executed, here it converts the files according to your request. As pointed out by @slhck you need to use such a complex command, so that dirnames with whitespaces won't break anything.[Edit]: Another variant to convert all HTML files under the current directory:
iname
searches case insensitive for*.html
.${filename%.*}.txt
strips the extention and appends.txt
, i.e. iffilename
issome/path/index.html
,${filename%.*}
issome/path/index
and finally${filename%.*}.txt
issome/path/index.txt
.When you use the Z shell, you can use a much cleaner for loop, without braking at white spaces:
The trick here is that
*(/)
does filename generation, but only returns directories(/)
.[Edit]: Also in zsh syntax the variant to convert all HTML files under the current directory (you need the option
EXTENDEDGLOB
to be set):(#i)
uses case insensitive globbing,**
searches recursively, hence returning all HTML files under the current working directory. (If symbolic links should be followed, use three stars***
instead of two).If you have more than one command inside the for loop, use curly
{ ... }
brackets (unnecessary here, but they won't hurt).${i:r}
strips the extention (r for remove) from the variable$i
.