パターンに一致するファイルの数をカウントする bash コマンドはありますか?
たとえば、次のパターンに一致するディレクトリ内のすべてのファイルの数を取得したいとします。log*
パターンに一致するファイルの数をカウントする bash コマンドはありますか?
たとえば、次のパターンに一致するディレクトリ内のすべてのファイルの数を取得したいとします。log*
この単純なワンライナーは、bash だけでなく、どのシェルでも機能するはずです。
ls -1q log* | wc -l
ls -1q は、空白や改行などの特殊文字が含まれている場合でも、ファイルごとに 1 行を提供します。
出力は、行数をカウントする wc -l にパイプされます。
ここにはたくさんの答えがありますが、考慮されていないものもあります
-l
)*.log
がlog*
logs
一致するという名前のディレクトリlog*
)それらすべてを処理するソリューションは次のとおりです。
ls 2>/dev/null -Ubad1 -- log* | wc -l
説明:
-U
ls
エントリをソートしません。つまり、ディレクトリ リスト全体をメモリにロードする必要はありません。-b
非グラフィック文字の C スタイルのエスケープを出力し、決定的に改行が として出力され\n
ます。-a
log*
隠しファイルを含むすべてのファイルを出力します (グロブが隠しファイルを意味しない場合は厳密には必要ありません)-d
ディレクトリの内容を一覧表示しようとせずにディレクトリを出力します。これはls
通常行うことです。-1
それが1つの列にあることを確認します(lsはパイプへの書き込み時にこれを自動的に行うため、厳密には必要ありません)2>/dev/null
ログ ファイルが 0 の場合にエラー メッセージを無視するように stderr をリダイレクトします。(代わりに作業ディレクトリ全体をリストshopt -s nullglob
する原因になることに注意してください。)ls
wc -l
はディレクトリ リストを生成時に消費するため、 の出力はls
どの時点でもメモリ内にはありません。--
--
ファイル名は、引数として理解されないように使用するコマンドから分離されますls
(削除された場合log*
)シェルはファイルの完全なリストに展開log*
しますが、ファイルが多い場合はメモリを使い果たす可能性があるため、grep を使用して実行することをお勧めします。
ls -Uba1 | grep ^log | wc -l
この最後のものは、大量のメモリを使用せずにファイルの非常に大きなディレクトリを処理します (ただし、サブシェルを使用します)。現在のディレクトリの内容をリストするだけなので、これ-d
は不要になりました。
\n
これは、bash を使用して安全に行うことができます (つまり、スペースを含むファイルや名前にバグが発生することはありません)。
$ shopt -s nullglob
$ logfiles=(*.log)
$ echo ${#logfiles[@]}
ファイルが一致しない場合に配列nullglob
にリテラルを取得しないように有効にする必要があります。(安全にリセットする方法の例については、「set -x」を「元に戻す」方法を参照してください。)*.log
$logfiles
再帰検索の場合:
find . -type f -name '*.log' -printf x | wc -c
wc -c
の出力の文字数をカウントし、find
結果ごとに 1 つの文字を出力する-printf x
よう指示します。find
x
非再帰検索の場合は、次のようにします。
find . -maxdepth 1 -type f -name '*.log' -printf x | wc -c
この質問に対する受け入れられた回答は間違っていますが、担当者が少ないため、コメントを追加できません。
この質問に対する正しい答えは、Mat によって与えられます。
shopt -s nullglob
logfiles=(*.log)
echo ${#logfiles[@]}
受け入れられた回答の問題は、 wc -l が改行文字の数をカウントし、端末に「?」として出力されてもカウントすることです。「ls -l」の出力で。これは、ファイル名に改行文字が含まれている場合、受け入れられた回答が失敗することを意味します。提案されたコマンドをテストしました:
ls -l log* | wc -l
また、名前に改行文字が含まれているパターンに一致するファイルが 1 つしかない場合でも、誤って値 2 を報告します。例えば:
touch log$'\n'def
ls log* -l | wc -l
ls -1 log* | wc -l
つまり、1行に1つのファイルをリストし、それを単語数コマンドにパイプして、パラメーターを数行に切り替えます。
すべてをカウントするには、ls を単語カウント行にパイプするだけです。
ls | wc -l
パターンでカウントするには、最初に grep にパイプします。
ls | grep log | wc -l