The most POSIX way to do this is probably to use the find
command with multiple -exec
options.
Update: A fully POSIX solution is at the end of this post.
You can locate nested directories named "cache" under the /home/demo
path like so:
find /home/demo -mindepth 2 -maxdepth 2 -type d -name cache
mindepth
and maxdepth
values of 2
restrict the search to immediate child directories
-type d
designates that you only want to find directories
-name cache
tells it to only return matches that are named exactly "cache"
You can then use the -exec
option to perform actions based on matched results. For example, if you wanted to run ls
to list the contents of each matched cache directory:
find /home/demo -mindepth 2 -maxdepth 2 -type d -name cache -exec ls {} \;
-exec
calls the following command that follows it (ls
) for each match
{}
returns the value of the match (in this case the path to the cache directory)
\;
tells it to perform the command one time for each match
So if you want to delete the contents of the directory, you can replace the ls
command above with an appropriate rm
statement—something like sh -c 'rm "{}"/*'
Example (DO NOT RUN THIS):
find /home/demo -maxdepth 2 -mindepth 2 -type d -name cache -exec sh -c 'rm "{}"/* 2>/dev/null' \;
In the above example sh -c
is used to allow for shell expansion of the /*
to match nested files (that's not very POSIX though). You could then add another -exec
as well to create an additional file.
Example (DO NOT RUN THIS):
find /home/demo -maxdepth 2 -mindepth 2 -type d -name cache -exec sh -c 'rm "{}"/* 2>/dev/null' \; -exec touch "{}/index.html" \;
In the above example two -exec
options are used together. The second one, which creates a nested index.html
file, only runs if the first -exec
command completes successfully.
It's maybe better to split this into multiple find commands, though—one to match and remove the files, and another to create the index.html
.
Example (DO NOT RUN THIS):
find /home/demo -mindepth 3 -maxdepth 3 -wholename "/home/demo/*/cache/*" -exec rm -rf "{}" \;
find /home/demo -maxdepth 2 -mindepth 2 -type d -name cache -exec touch "{}/index.html" \;
In the first statement:
-mindepth
and -maxdepth
of 3
only matches children of children
-wholename "/home/demo/*/cache/*"
provides a match to children of the target cache directories
The second statement then creates the index.html
files.
If I understood your question correctly, then that command pair probably does what you're looking for. But read it carefully and make sure you fully understand it before using it.
I recommend prefixing any rm
and touch
commands with the echo
command before running anything. That should let you have a dry run to see what it's doing.
Example (safe dry run using echo
):
find /home/demo -mindepth 3 -maxdepth 3 -wholename "/home/demo/*/cache/*" -exec echo rm -rf "{}" \;
find /home/demo -maxdepth 2 -mindepth 2 -type d -name cache -exec echo touch "{}/index.html" \;
Update - Fully POSIX Solution (but harder to read):
For a fully POSIX equivalent (no mindepth
/maxdepth
/wholename
) you can use a positive/negative -path
combination using find
's internal globbing.
It's significantly easier if you cd
into your working tree first, as you won't have to count the leading directories for your glob patterns.
cd /home/demo
find . -path "./*/cache/*" ! -path "./*/*/*/*" -exec echo rm -rf {} \;
find . -type d -path "./*/cache" ! -path "./*/*/*" -exec echo touch {}/index.html \;
Remove the echo
statements if you get the expected result.