Answers:
假设find
像GNU find
这样的实现接受{}
嵌入到以下参数的参数-exec
:
$ find . -type d \! -exec test -e '{}/README' \; -print
这里的目录1/1至5/5具有自述文件,其他目录为空。
$ 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
With zsh
和Glob限定词(e
字符串):
print -rl -- *(/e_'[[ ! -f $REPLY/README ]]'_)
要么
print -rl -- *(/^e_'[[ -f $REPLY/README ]]'_)
添加D
以包含隐藏目录:
print -rl -- *(D/e_'[[ ! -f $REPLY/README ]]'_)
/
仅选择目录,并仅e_'[[ ! -f $REPLY/README ]]'_
选择引号之间的外壳程序代码返回的true
目录名称$REPLY
,即对于glob *(/)
扩展到的每个目录名称(),[[ ! -f $REPLY/README ]]
如果结果为,它将运行并保留目录名称true
。
第二种形式^e_'.....'_
使用相同的glob限定符,取反(但这次条件表达式不取反:)[[ -f $REPLY/README ]]
。
上面只会返回当前目录中的目录名称。
如果要递归搜索(同样,要包含隐藏目录,请添加D
限定符):
print -rl ./**/*(/e_'[[ ! -f $REPLY/README ]]'_)
可移植地,您可以执行以下操作:
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中是否不存在常规文件?在这样。