List all directories that do NOT have a file with a given file name inside
Assuming a find
implementation like GNU find
that accepts a {}
embedded in an argument to -exec
:
$ find . -type d \! -exec test -e '{}/README' \; -print
or, without the problematic embedding:
$ find . -type d ! -exec sh -c 'test -e "$1"/README' sh {} \; -print
Example
Here directories 1/1 through 5/5 have a README, the other dirs are empty.
$ tree
.
|-- 1
| `-- 1
| `-- README
|-- 10
| `-- 10
|-- 2
| `-- 2
| `-- README
|-- 3
| `-- 3
| `-- README
|-- 4
| `-- 4
| `-- README
|-- 5
| `-- 5
| `-- README
|-- 6
| `-- 6
|-- 7
| `-- 7
|-- 8
| `-- 8
`-- 9
`-- 9
Now when we run this version of our find
command:
$ find . -type d \! -exec test -e '{}/README' \; -print
.
./10
./10/10
./7
./7/7
./9
./9/9
./6
./6/6
./5
./8
./8/8
./4
./1
./3
./2
References
- Exclude directories in find that don't contain a specific filename?
No need for find
. Just use the shell:
for d in */; do [ -f "$d"README ] || printf '%s\n' "$d"; done
c/
If you need it to be recursive, you can use (for bash
, zsh
can do this by default, use set -o globstar
in ksh93
):
shopt -s globstar
for d in **/; do [ -f "$d"README ] || printf '%s\n' "$d"; done
(note that dot-files are excluded by default).
You can use the -exec
option of find
to check for the file, and then print all results for which the check fails.
find /path/to/base -mindepth 1 -maxdepth 1 -type d -exec test -e {}/README \; -o -print