我将如何列出所有目录不是里面有一个给定文件名的文件吗?例如给定这棵树
/
/a
README
file001
file002
/b
README
file001
/c
file003
我想列出执行此操作的目录不是有一个名为 的文件README
,在本例中它将是目录/c
。我该怎么做呢?我想不出任何使用例如的语法find
。
答案1
假设find
像 GNUfind
这样的实现接受{}
嵌入在参数中-exec
:
$ find . -type d \! -exec test -e '{}/README' \; -print
或者,没有有问题的嵌入:
$ find . -type d ! -exec sh -c 'test -e "$1"/README' sh {} \; -print
例子
这里目录 1/1 到 5/5 有一个 README,其他目录是空的。
$ 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
现在,当我们运行此版本的find
命令时:
$ 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
参考
答案2
不需要find
。只需使用外壳:
for d in */; do [ -f "$d"README ] || printf '%s\n' "$d"; done
c/
如果需要递归,可以使用(对于bash
,zsh
默认可以这样做,set -o globstar
在 中使用ksh93
):
shopt -s globstar
for d in **/; do [ -f "$d"README ] || printf '%s\n' "$d"; done
(请注意,默认情况下排除点文件)。
答案3
您可以使用-exec
选项来find
检查文件,然后打印检查失败的所有结果。
find /path/to/base -mindepth 1 -maxdepth 1 -type d -exec test -e {}/README \; -o -print
答案4
便携地,你可以这样做:
find . -type d -exec sh -c '
for dir do
[ -f "$dir/README" ] || printf "%s\n" "$dir"
done' sh '{}' +
[ -f file ]
测试文件是否存在 和被确认为常规文件(符号链接解析后)。
如果您想测试它是否仅存在(作为该目录中的条目),无论其类型如何,您都需要:[ -e file ] || [ -L file ]
,但请注意,您需要对该目录的搜索权限才能执行这些测试。您可能需要添加一些[ -x "$dir" ]
测试来解释这些情况,例如:
find . -type d -exec sh -c '
for dir do
if [ -x "$dir" ]; then
[ -f "$dir/README" ] || printf "%s\n" "$dir"
else
printf >&2 "Cannot tell for \"%s\"\n" "$dir"
fi
done' sh '{}' +
或者为了避免竞争条件,使用zsh
:
find . -type d -exec zsh -c '
zmodload zsh/system
for dir do
ERRNO=0
if [ ! -f "$dir/README" ]; then
if [ "$errnos[ERRNO]" = ENOENT ]; then
printf "%s\n" "$dir"
else
syserror -p "ERROR: $dir/README: "
fi
fi
done' zsh '{}' +
也可以看看如何判断 Bash 中是否不存在常规文件?就这样。