ls *.txt | wc -l
多くのファイルを含むディレクトリにアクセスしようとすると、次のエラーが発生します。
-bash: /bin/ls: Argument list too long
この「パラメータリスト」のしきい値は、システムの展開または仕様によって異なりますか?通常、このような大きな結果を他のコマンド(例:)にパイプするため、wc -l
端末の制限は気にしません。
答え1
エラーメッセージパラメータリストが長すぎます。~から*のls *.txt
。
この制限はバイナリとカーネルの両方に安全です。バラよりARG_MAX、新しいプロセスの最大パラメータ長これに関する詳細情報と使用方法と計算方法。
パイプサイズにはそのような制限はありません。したがって、単に次のコマンドを実行できます。
find -type f -name '*.txt' | wc -l
ls
注:最新のLinuxでは、ファイル名の奇妙な文字(改行文字など)が同じツールを使用してエスケープされますが、find
まだ表示されます。*。以前のUnixを使用している場合は、このコマンドが必要です。
find -type f -name '*.txt' -exec echo \; | wc -l
NB2:名前に改行文字を含むファイルを作成する方法を知りたいです。コツを知ったら難しくありません。
touch "hello
world"
答え2
これは主にLinuxカーネルのバージョンによって異なります。
以下を実行してシステムの制限を確認できる必要があります。
getconf ARG_MAX
これは、シェルによる拡張後にコマンドラインが持つことができる最大バイト数を示します。
Linux < 2.6.23では、制限は通常128KBです。
Linux> = 2.6.25では、制限は128KBまたはスタックサイズ(参考資料を参照ulimit -s
)の1/4のうち大きい方です。
よりexecve(2) マニュアルページすべての詳細を確認してください。
残念ながら、配管はls *.txt
問題を解決しません。なぜなら、その制限はシェルではなくオペレーティングシステムにあるからです。
シェルが展開された*.txt
後に呼び出しを試みます。
exec("ls", "a.txt", "b.txt", ...)
そして、一致するファイルが多すぎて*.txt
128KBの制限を超えました。
あなたは次のことをする必要があります
find . -maxdepth 1 -name "*.txt" | wc -l
代わりに。
(改行文字を含むファイル名については、以下のShawn J. Goffの説明を参照してください。)
答え3
別の回避策:
ls | grep -c '\.txt$'
ls
生産よりも多くの出力を生成してもls *.txt
(または生産しようとした場合)、通過できなかったため、「引数が長すぎる」という問題は発生しません。どの買収ls
。grep
ファイル一致パターンではなく正規表現を使用していることに注意してください。
以下を使用できます。
ls -U | grep -c '\.txt$'
(あなたのバージョンがls
このオプションをサポートしていると仮定してください)。これはls
出力をソートしないように指示し、時間とメモリを節約します。この場合、ファイル数を数えるので、順序は重要ではありません。一般に、出力をソートするのに必要なリソースは重要ではありませんが、この場合はすでに多数の*.txt
ファイルがあることがわかります。
そして、単一のディレクトリにあまりにも多くのファイルが含まれないようにファイルを再構成することを検討する必要があります。これは実現可能でも不可能でもよい。
答え4
MAX_ARG_PAGESはカーネルパラメータのようです。find
andを使用することはxargs
この制限を解決するための一般的な組み合わせですが、それがうまくいくかどうかはわかりませんwc
。
出力をfind . -name \*\.txt
ファイルにパイプしてそのファイルの行数を数えると、問題を解決できます。