ファイルが見つかったら、検索ツリーのクリーンアップ

ファイルが見つかったら、検索ツリーのクリーンアップ

名前が特定のファイル名ワイルドカードパターンと一致する一般的なファイルを見つけるには、かなり大きなディレクトリ階層を検索する必要があります。階層が大きすぎて(非常に深くて巨大なディレクトリがある)、単純なアプローチでは時間がかかりすぎます。

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/dirpatternおよびを変更する必要があります。*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ここではコード自体が十分に不透明です。

関連情報