You can't use find
to look for files that do not exist. However, you may use find
to look for directories, and then test whether the given filenames exists in those directories.
When using find
to look for directories, make sure that you use -type d
. Then test each of the found directories for the files README
and readme
.
Assuming the following directory hierarchy for some top-directory projects
:
projects/
|-- toola
| |-- doc
| |-- readme
| `-- src
|-- toolb
| |-- doc
| `-- src
|-- toolc
| |-- README
| |-- doc
| `-- src
`-- toold
|-- doc
`-- src
Using find
to find the directories directly under projects
that does not contain a README
or readme
file:
$ find projects -mindepth 1 -maxdepth 1 -type d \
! -exec test -f {}/README ';' \
! -exec test -f {}/readme ';' -print
projects/toolb
projects/toold
Here, we find any directory directly under projects
and then use the test
utility to determine which one of the found directories do not contain either of the two files.
This is exactly equivalent of
find projects -mindepth 1 -maxdepth 1 -type d \
-exec [ ! -f {}/README ] ';' \
-exec [ ! -f {}/readme ] ';' -print
Another formulation of the above:
find projects -mindepth 1 -maxdepth 1 -type d -exec sh -c '
for pathname do
if [ ! -f "$pathname/README" ] &&
[ ! -f "$pathname/readme" ]; then
printf "%s\n" "$pathname"
fi
done' sh {} +
Here, we let a small in-line shell script do the actual testing for the two files and print the pathname of the directories that does not contain either of them. The find
utility acts like a "pathname generator" of pathnames to directories for the in-line script to iterate over.
In fact, if the directory structure is like this, we may choose to not use find
at all:
for pathname in projects/*/; do
if [ ! -f "$pathname/README" ] &&
[ ! -f "$pathname/readme" ]; then
printf '%s\n' "$pathname"
fi
done
Note the trailing slash in the projects/*/
pattern. It's this that makes the pattern only match directories (or symbolic links to directories).
A difference between doing it this way and using find
is that with the above shell loop, we will exclude hidden directories under project
and will include symbolic links to directories.
In all cases, we iterate over the pathnames of directories, and we test for the non-existence of the two filenames.
The only caveat is that the -f
test will also be true for a symbolic link to a regular file.
Related:
-exec
for its intended use and not as a weakerxargs
.. – pipe Oct 24 '18 at 12:51xargs
has its uses, but we don't often need it. – Kusalananda Oct 24 '18 at 12:53