*Tags*: cmd:find
Newsgroups: comp.unix.shell Date: 26 Nov 2006 21:51:03 -0800
> Is there any way to find which dir (under cwd) is empty? I.e., has no > file in it but may have sub dirs?
Here is one way. Note that this is breaks if there are paths with spaces in them:
find . -type d -exec sh -c '[ -z "$(find '{}' -maxdepth 1 ! -type d -print)" ]' \; -printKaz Kylheku
> Note that this is breaks if there are paths with > spaces in them.
$ find . -type d -exec sh -c '[ -z "$(find '{}' -maxdepth 1 ! -type d -print)" ]' \; -print
find: ./af/empty: No such file or directory
find: dir: No such file or directory
./af/empty dir$ find . -type d -exec sh -c '[ -z "$(find '\''{}'\'' -maxdepth 1 ! -type d -print)" ]' \; -print
./af/empty dir
./af/empty dir/subd$ find . -type d -exec sh -c '[ -z "$(find "'{}'" -maxdepth 1 ! -type d -print)" ]' \; -print
./af/empty dir
./af/empty dir/subdT
> > Here is one way. Note that this is breaks if there are paths with
> > spaces in them:
> >
> > find . -type d -exec sh -c '[ -z "$(find '{}' -maxdepth 1 ! -type d
> > -print)" ]' \; -print
>
> Thanks, that works.
>
> May I know why it will break when there are spaces in path name?
>
> find: ./af/empty: No such file or directory
> find: dir: No such file or directory
> ./af/empty dir
>
> I saw that the {} has been quoted with ''. Why is the quote ignored?That's a mistake. Note that the entire argument to sh -c is in single quotes. So these inner quotes break that up into two single-quoted pieces with {} in the middle. It doesn't matter if you remove these; either way, it breaks.
To fix the problem, you have to get {} to be quoted. Here is how. Switch to double quotes, and then escape them within. Command expansion takes place now so you have to escape that too, you want the embedded sh -c to evaluate the $(find …), not the outer command:
find . -type d -exec sh -c "[ -z \"\$(find \"{}\" -maxdepth 1 ! -type d -print)\" ]" \; -printThe real challenge would be protecting this against expansions of {} which look like a predicate, valid or otherwise.
Kaz Kylheku
> To fix the problem, you have to get {} to be quoted. Here is how.
> Switch to double quotes, and then escape them within. Command expansion
> takes place now so you have to escape that too, you want the embedded
> sh -c to evaluate the $(find ...), not the outer command:
>
> find . -type d -exec sh -c "[ -z \"\$(find \"{}\" -maxdepth 1 ! -type d
> -print)\" ]" \; -printHi, thank you Kaz for the detailed explanation.
FYI, I found the following sufficient enough under Linux, in which sh is actually bash:
$ find . -type d -exec sh -c '[ -z "$(find "'{}'" -maxdepth 1 ! -type d -print)" ]' \; -print
./af/empty dir
./af/empty dir/subd