多くのファイルを含むディレクトリをls *.txt | wc -l
しようとすると、次のエラーが発生します。
-bash: /bin/ls: Argument list too long
この「引数リスト」のしきい値は、ディストリビューションまたはコンピューターの仕様に依存しますか?通常、私はそのような大きな結果の結果を他のいくつかのコマンド(たとえば、wc -l
)にパイプします。そのため、端末の制限は関係ありません。
エラーメッセージが長すぎる引数リストはls *.txt
。
この制限は、バイナリプログラムとカーネルの両方にとって安全です。詳細、およびその使用方法と計算方法については、 ARG_MAX、新しいプロセスの引数の最大長 を参照してください。
パイプサイズにそのような制限はありません。したがって、次のコマンドを発行するだけです。
find -type f -name '*.txt' | wc -l
注意:最近のLinuxでは、ファイル名に含まれる奇妙な文字(改行など)はls
やfind
などのツールでエスケープされますが、*****からは表示されます。古いUnixを使用している場合は、このコマンドが必要になります
find -type f -name '*.txt' -exec echo \; | wc -l
NB2:名前に改行を含むファイルを作成する方法を知りたいと思っていました。トリックを知っていれば、それほど難しくありません。
touch "hello
world"
それは主にLinuxカーネルのバージョンに依存します。
実行すると、システムの制限を確認できるはずです。
getconf ARG_MAX
これは、シェルによって展開された後のコマンドラインの最大バイト数を示します。
Linux <2.6.23では、制限は通常128 KBです。
Linux> = 2.6.25では、制限は128 KB、またはスタックサイズの1/4(ulimit -s
を参照)のいずれか大きい方です。
詳細は execve(2)man page を参照してください。
残念ながら、制限はシェルではなくオペレーティングシステムにあるため、ls *.txt
をパイプしても問題は解決しません。
シェルは*.txt
を展開してから、
exec("ls", "a.txt", "b.txt", ...)
また、*.txt
に一致するファイルが多すぎるため、128 KBの制限を超えています。
あなたは次のようなことをしなければならないでしょう
find . -maxdepth 1 -name "*.txt" | wc -l
代わりに。
(改行を含むファイル名については、以下のShawn J. Goffのコメントを参照してください。)
別の回避策:
ls | grep -c '\.txt$'
ls
は、ls *.txt
が生成する(または生成しようとする)よりも多くの出力を生成しますが、anyを渡していないため、「引数が長すぎます」の問題には遭遇しませんls
への引数。 grep
は、ファイルマッチングパターンではなく正規表現を使用することに注意してください。
あなたは使いたいかもしれません:
ls -U | grep -c '\.txt$'
(お使いのバージョンのls
がこのオプションをサポートしていると想定しています)。これは、ls
に出力をソートしないように指示します。これにより、時間とメモリの両方を節約できます。この場合、ファイルを数えるだけなので、順序は関係ありません。通常、出力のソートに費やされるリソースは重要ではありませんが、この場合、非常に多数の*.txt
ファイルがあることがわかっています。
また、1つのディレクトリに多くのファイルが存在しないように、ファイルを再編成することを検討する必要があります。これは可能かもしれませんし、可能でないかもしれません。
MAX_ARG_PAGESはカーネルパラメータのようです。 find
とxargs
を使用することは、この制限に対処するための一般的な組み合わせですが、wc
で機能するかどうかはわかりません。
find . -name \*\.txt
の出力をファイルにパイプし、そのファイルの行を数えると、回避策として機能します。
これは汚いかもしれませんが、私のニーズと私の能力の範囲内で機能します。私はそれが非常に速く機能するとは思わないが、私の一日を続けることができた。
ls | grep jpg | <something>
90,000のjpgの長いリストを取得し、それらをavconvにパイプしてタイムラプスを生成していました。
以前はls * .jpgを使用していました|この問題に遭遇する前にavconv。