Shell – find all directories (except `encoded`) in the working dir then delete all of them

findrmshell-script

I am trying to test this scenario, I have these files

/encoded
encode <~~~ a bash script
/dir1
/dir2
.../dir2-sub
test.meta

what I wish is, for find to search for all directories in our current (except) encoded, then delete all of them

I ended up using this script:

find . -name encoded -prune -o -maxdepth 10 ! -name 'encode*' ! -name '.*' | xargs rm -rf

what I believe it would do is, mark the folder encoded then -prune it, so it would ignore it, right?
then for any other, which does not have extension(which makes sure all of them are dir) delete it via rm

but the problem is… I also have a bash script without extension name, so it ended up getting deleted

what i wish is my bashscript to end up from the structure above to exactly like this one (keeping all non-dir intact, don't touch /encoded folder and its contents, and don't delete encode bash script)

/encoded
encode <~~~ a bash script
test.meta

how can I get the result above?

Best Answer

You don't need to recursively enumerate directories to delete them with rm -rf; you can simply list the top-level directories you want to delete. To determine whether a directory entry is a directory rather than a file, you can use find's -type d test; using . isn't a good indicator.

The following should work for you:

find * -maxdepth 0 ! -name encoded -type d -print0 | xargs -0 rm -rf

This starts from all the entries in the current directory (to avoid listing .), drops anything whose name is encoded, and keeps only directories; it outputs the result using a null as delimiter, and feeds the result into xargs to give to rm -rf. Before running this variant, try

find * -maxdepth 0 ! -name encoded -type d

to see if the output matches what you expect.

-prune doesn't ignore its match, it avoids descending into it; so in your example, encoded is still listed, and then filtered by the -name test.

Related Question