名前が特定のファイル名ワイルドカードパターンと一致する一般的なファイルを見つけるには、かなり大きなディレクトリ階層を検索する必要があります。階層が大きすぎて(非常に深くて巨大なディレクトリがある)、単純なアプローチでは時間がかかりすぎます。
find /top/dir -type f -name 'pattern'
(pattern
類似パターンはどこにありますか*proj*.tgz
?)
ディレクトリ構造の性質のためにfind
ディレクトリにファイルが見つかった場合は、検索ツリーをクリーンアップするために最適化を導入できることがわかります。たとえば、特定のディレクトリで1つ以上のファイルを見つけることは、その特定のディレクトリのサブディレクトリで他の一致を確認する必要がないことを意味します。
通常のファイルに適用するのが正しくないため、-prune
これはできません。
find /top/dir -type f -name 'pattern' -prune
質問:パターンに一致するファイルを含むディレクトリのサブディレクトリ検索を防ぐにはどうすればよいですか?
答え1
各ディレクトリに対してインラインスクリプトを呼び出すことができます。スクリプトは、パターンがディレクトリの通常のファイルと一致することを確認します。パターンが一致すると、出力(通常プロセス単に印刷する代わりに、パス名を一致させ、検索ツリーで親ディレクトリをクリーンアップします。
find /top/dir -type d -exec zsh -c '
set -- "$1"/pattern(.N)
[[ $# -eq 0 ]] && exit 1
printf "%s\n" "$@"' zsh {} \; -prune
インラインスクリプトのシェルを使用して、シェルのグローバル修飾zsh
子にアクセスします。ここで使用される修飾子は、(.N)
通常のファイルのみがパターンと一致することを確認し、一致するファイルが存在しない場合はパターンが削除されます。
bash
インラインスクリプトの場合:
find /top/dir -type d -exec bash -O nullglob -c '
unset -v found
for pathname in "$1"/pattern; do
if [[ -f "$pathname" ]] && [[ ! -h "$pathname" ]]; then
printf "%s\n" "$pathname"
found=true
fi
done
"${found-false}"' bash {} \; -prune
つまり、特定のディレクトリのパターンと一致する名前を介してインラインスクリプトループを持ち、名前が通常のファイルに対応する場合はそれを処理して「フラグ」を設定します。このフラグが最後に設定されると、親ディレクトリがクリーンアップされます。
答え2
ディレクトリ階層を参照してフラグファイルが見つかった場合は、各ディレクトリのツリーをクリーンアップし()、pattern
それ以外の場合は必要なファイルを検索します(*proj*.tgz
)。
find /top/dir -type d -exec sh -c 'z=$(find "$@" -maxdepth 1 -type f -name "pattern" -print -quit); [ -n "$z" ]' _ {} \; -prune -o -type f -name '*proj*.tgz' -print
私は何が起こっているのかを見るためのより複雑なバージョンを書くようになりました。明らかに地域関連項目を取得するには/top/dir
、pattern
およびを変更する必要があります。*proj*.tgz
)後でこれのためにここに含めます。
find /top/dir -type d \
-exec bash -c '
echo "Considering $*";
z=$(find "$@" -maxdepth 1 -type f -printf "| %p\n" -name "pattern" -printf "Found flag file\n" -quit);
[[ -n "$z" ]] && echo "$z";
[[ "$z" =~ "Found flag file" ]] || { echo "No flag found"; exit 1; }
' _ {} \; \
-printf "Pruning tree\n" -prune \
-o \
-type f -name '*proj*.tgz' -print
実際のソリューションにはPOSIX以外のものが必要ですfind -maxdepth
。デバッグビルドにはPOSIX以外のビルドも必要ですfind -printf
。一つある代替方法POSIX準拠を実装するために使用されますが、-maxdepth
ここではコード自体が十分に不透明です。