私は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は同じディレクトリ名を複数回検索するのを防ぐための礼儀です。削除するディレクトリのリストがある場合は、入力ストリーム(すべてのディレクトリのマスターリスト)から括弧内のコマンド置換によって生成された各ディレクトリ(ファイルの場所のリスト)を削除します。残りの出力は、ファイルが含まれていないディレクトリのセットです。*.bam
mypath/
sort
uniq
uniq
grep
grep
*.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