特定の名前のファイルが複数のディレクトリに存在することを確認する

特定の名前のファイルが複数のディレクトリに存在することを確認する

私はLinuxを初めて使用しますが、これが可能かどうかを知りたいです。ディレクトリにファイル名のサフィックスが付いたファイルがあるかどうかを確認したいと思います。.bam確認するディレクトリは何百ものあります。私はこれを手動で実行したくありません。したがって、すべてのディレクトリを確認して出力することは可能ですか?そのファイルのリストがありません

答え1

存在するzsh

if ()(($#)) **/*.bam(ND.Y1)); then
  print There is at least one regular file in here whose name ends in .bam
fi
directories_without_bam=(
  **/*(ND/^e['()(($#)) $REPLY/*.bam(ND.Y1)'])
)

if (( $#directories_without_bam )); then
  print "Directories without bam files:"
  printf ' - %s\n' $directories_without_bam
fi

現在の作業ディレクトリ()自体は見ておらず、.その下にあるディレクトリだけを見てください。変更も考慮されます**/*。 ){.,**/*}.

答え2

bashシェルを使用すると、現在のディレクトリにで終わる名前が含まれているかどうかをテストし.bam、そうでない場合は、次のようにメッセージを印刷できます。

shopt -s dotglob nullglob
set -- ./*.bam
[ "$#" = 0 ] && echo 'nothing found'

シェルdotglobオプションは*隠された名前のマッチングを可能にし、一致するnullglobものがなければパターンを変更せずにそのままにする代わりにパターンを削除します。

setパターンを展開し、位置引数のリストを一致する名前に設定できます。位置引数リストの長さが0の場合、$#パターンと一致する名前はありません。

findこのコードは、現在のディレクトリとその下のすべてのディレクトリに適用できます。

find . -type d -exec bash -O dotglob -O nullglob -c '
    for d do
        set -- "$d"/*.bam
        [ "$#" = 0 ] && printf "%s\n" "$d"
    done' bash {} +

これは最初からすべてのディレクトリを再帰的に見つけ、与えられた.インラインbashスクリプトに一括して供給します。スクリプトは指定されたディレクトリパスを繰り返し、setコマンドとテストを順番に適用して、一致する名前を生成しなかったディレクトリのパス名を出力します。


シェルには、failglobパターンが何も一致しない場合に失敗を生成するシェルオプションもあります。これを使用してコードを少し短く(小さく!)作成することができますが、読みやすくするのは難しくなります。

find . -type d -exec bash -O dotglob -O failglob -c '
    for d do
        (set -- "$d"/*.bam) 2>/dev/null || printf "%s\n" "$d"
    done' bash {} +

答え3

@waltinatorのcommユーティリティアイデアと同様に、grep標準入力から文字列セットを削除するために使用できます。

$ find mypath/ -type d | 
    grep -Fvxf <(find mypath/ -name \*.bam -type f -exec dirname {} \; | sort | uniq)

構文を説明するために、パイプの左側にその下のすべてのディレクトリのリストを作成しますmypath/。右の括弧に注意してください。数学と同様に、この部分は最初に完了します。以下のすべてのファイルをfind検索しますが、各ファイルのディレクトリパスのみを印刷します。その後、その出力が編集され(おそらく不要ですが時間がかかりません)、各ディレクトリ名が一度だけ表示されるように編集されます。 ingは同じディレクトリ名を複数回検索するのを防ぐための礼儀です。削除するディレクトリのリストがある場合は、入力ストリーム(すべてのディレクトリのマスターリスト)から括弧内のコマンド置換によって生成された各ディレクトリ(ファイルの場所のリスト)を削除します。残りの出力は、ファイルが含まれていないディレクトリのセットです。*.bammypath/sortuniquniqgrepgrep*.bam*.bam

答え4

@waltinatorがコメントで述べたように、findコマンドを使用できます。

find /your/path -type d '!' -exec sh -c 'ls -1 "{}" | egrep -i -q "^.*\.bam$"' ';' -print

説明を見つけることができますここ

サンプル出力:

$ find /usr/libexec -type d '!' -exec sh -c 'ls -1 "{}"|egrep -i -q "^.*\.so$"' ';' -print
/usr/libexec
/usr/libexec/emacs
/usr/libexec/emacs/29.1
/usr/libexec/emacs/29.1/x86_64-pc-linux-gnu
/usr/libexec/man-db
/usr/libexec/gcc
/usr/libexec/gcc/x86_64-pc-linux-gnu
/usr/libexec/gcc/x86_64-pc-linux-gnu/13/plugin
/usr/libexec/git-core
/usr/libexec/git-core/mergetools
/usr/libexec/podman
/usr/libexec/nullmailer

関連情報