*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)" ]' \; -print
Kaz 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/subd
T
> > 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)\" ]" \; -print
The 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)\" ]" \; -print
Hi, 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