
全てのディレクトリをリストするにはどうすればいいでしょうか?ない指定されたファイル名のファイルがありますか?例えば、このツリーが与えられた場合
/
/a
README
file001
file002
/b
README
file001
/c
file003
ディレクトリを一覧表示したいないという名前のファイルがありREADME
、この場合はディレクトリ になります/c
。どうすればいいでしょうか? たとえば を使用する構文が思いつきませんfind
。
答え1
引数に埋め込まれた を受け入れるfind
GNU のような実装を想定すると、次のようになります。find
{}
-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 '{}' +