ディレクトリから見つからないファイルを見つけて印刷するには?

ディレクトリから見つからないファイルを見つけて印刷するには?

.gridで終わるファイルを含む親ディレクトリのすべてのディレクトリを見つけて一覧表示したいと思います。/work/user/folder1/*/*

find /work/user/folder1/*/*/ '!' -mindepth 1 -maxdepth 1 -name *.grid

次にやりたいことは、.gridで終わるファイルが見つからないすべてのディレクトリを見つけることです。デフォルトでは、欠落しているフォルダを印刷するコマンドが必要です。

どうすればいいですか?

答え1

find電話をかけるときに使用してくださいfind

find . -type d \( -exec sh -c 'cd "$0"; find . \( -name . -o -prune \) -name "*.grid" | grep -q .' {} \; -o -print \)

これはPOSIXに準拠しています。この回答ありがとうございます。

また、ファイル名やディレクトリ名にスペース、特殊文字、改行文字が含まれているかどうかに関係なく機能します。 :)

(注:もしあなたがするディレクトリ名に特殊文字または改行文字が含まれている場合は、-print最終mainをディレクトリ内の必要に応じて変更する必要があります。これは、.のみを使用すると結果の印刷リストを安全に解析できないためです-print。 )

以下は、読みやすくするために誤解を招く改行文字が追加されたバージョンです。

find . -type d \
  \( \
    -exec sh -c '
      cd "$0";
      find . \( -name . -o -prune \) -name "*.grid" |
        grep -q .
    ' {} \; \
    -o -print \
  \)

答え2

手順 1.) 該当するすべてのディレクトリのリストを作成し、英数字でソートし、重複するエントリがないことを確認します。一時ファイルにリストを保存します。

find /work/user/folder1/ [...] -type d | sort | uniq > all_directories.txt

ステップ2.)すべてのファイルのリストを作成します*.grid

find /work/user/folder1/ [...] -name *.grid > grid_files.txt

ステップ3。)ファイルのリストを調べて、*.grid各ファイルのディレクトリ名を取得してから、重複するエントリがないことを確認してください。

while read FILENAME
do
    echo $(dirname "$FILENAME")
done < grid_files.txt | sort | uniq > dirs_with_gridfiles.txt

ステップ4。)両方のリストを一緒に実行し、結果を並べ替えます。これで*.grid、ファイルを含むディレクトリを一覧表示する必要があります。正確にそれぞれ2回、ディレクトリに*.gridファイルがありません。正確にそれぞれ一回。したがって、uniq重複していない行のみを報告することがわかります。

cat all_directories.txt dirs_with_gridfiles.txt | sort | uniq -u > dirs_with_no_gridfile.txt

あなたはそれを得る。

答え3

これは2段階のソリューションです。全体として、プロセスは次のようになります。

  1. *.gridデフォルトのファイル名とリストを削除して、パス内のすべてのファイルを見つけますuniq。これにより、1つ以上のファイルを含むすべてのディレクトリのリストが表示されます*.grid

$ find /work/user/folder1/*/*/ -type f -name *.grid | sed -e 's-[^/]*$--' | sort | uniq > grid-dirs.txt

  1. パス内のすべてのディレクトリを検索し、grep手順1で見つけたディレクトリをフィルタリングするために使用します。これにより、*.gridファイルが含まれていないすべてのディレクトリのリストが表示されます。

$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt

たとえば、次のようにします。

$ find /work
/work
/work/user
/work/user/folder1
/work/user/folder1/AA
/work/user/folder1/AA/AA
/work/user/folder1/AA/DD
/work/user/folder1/AA/CC
/work/user/folder1/AA/BB
/work/user/folder1/AA/BB/foo.grid

ステップ1以降はgrid-dirs.txt次のようになります。

/work/user/folder1/AA/BB/

ステップ2の出力は次のとおりです。

$ find /work/user/folder1/*/*/ -type d | grep -Fvxf grid-dirs.txt
/work/user/folder1/AA/AA/
/work/user/folder1/AA/CC/
/work/user/folder1/AA/DD/

答え4

Bash v4(またはそれ以上)を使用している場合は、*.gridループ内のすべてのファイルとすべてのディレクトリを通過して、ファイルが存在するディレクトリと存在しないディレクトリを一覧表示する内部ループも見つけることができると思います。 Bash v4では、通常無効になっているオプションの1つを使用します。

(
# 'globstar' enables '**' expansions, which instructs
# the shell to search all and below recursively
shopt -s globstar

# Note that '**' is implicitly recursive, no need to specify
# depth. If you do want to specify precise depth, then use a
# '*/' for each wanted depth, like '*/*/*/' for 3 depths
for f in /work/user/folder1/**/*.grid; do
    f="${f##*/}"  # strip directory from found name
    printf '\nNow looking for: %s\n' "$f"
    # A simple '**/' returns directories only
    for d in /work/user/folder1/**/; do
        # simple existence test
        [ -e "${d}${f}" ] && \
            printf '    present in %s\n' "$d" || \
            printf 'not present in %s\n' "$d"
    done
done
)

残念ながら、**構文はPOSIXではありません。

ただし、検索する必要がある正確な深さがわかっている場合は、そのコマンドを削除して各コマンドを繰り返し表現されたshopt正確**/な深さに変換すると、*/POSIXシェルでもうまく機能します。

関連情報