引数リストがlsに対して長すぎます


48

ls *.txt | wc -l多くのファイルが含まれているディレクトリにアクセスしようとすると、次のエラーが表示されます。

-bash: /bin/ls: Argument list too long

この「引数リスト」のしきい値は、ディストリビューションまたはコンピューターの仕様に依存しますか?通常、このような大きな結果の結果を他のコマンド(wc -lたとえば)にパイプするので、端末の制限については気にしません。


6
これは構文解析lsの出力としてカウントされますが、これは悪い考えですので、避けてください。カウントについては、ディレクトリ内のファイル数をカウントする最良の方法何ですか?を参照してください、トリッキーな回避策については、forループで「引数が長すぎます」エラーが発生しない理由を参照してください
マナトワーク

@manatworkはい、私もそれらの質問を見ました。より一般的な方法で、コマンドからの長い出力を使用またはリダイレクトするより良い方法を考えているだけです。

getconf ARG_MAXを使用して、ほとんどのUNIXベースのシステムの制限を取得できます
Prasanth

回答:


49

あなたのエラーメッセージ引数リストが長すぎるから来ている*ls *.txt

この制限は、バイナリプログラムとカーネルの両方にとって安全です。このページには、その詳細と、その使用方法と計算方法が表示されます。

パイプサイズにそのような制限はありません。したがって、次のコマンドを発行するだけです。

find -type f -name '*.txt'  | wc -l

NBは:最近のLinuxでは、(改行など)、ファイル名に変な文字のようなツールを使ってエスケープされますlsfind、まだから表示します*。古いUnixを使用している場合、このコマンドが必要です。

find -type f -name '*.txt' -exec echo \;  | wc -l

NB2:名前に改行を含むファイルを作成するにはどうすればよいのかと思っていました。トリックを知ったら、それほど難しくありません:

touch "hello
world"

1
ファイル名に改行が含まれている場合に機能するように、少し変更しました。-maxdepth 1サブディレクトリ内のファイルをカウントするつもりがない場合は、aを追加することもできます。
ショーンJ.ゴフ

あなたは必要ありません-exec echo \;
ミケル

@ ShawnJ.Goff私はそれをテストしました。GNU findの現在のバージョンでは `echo`の必要はありません
Coren

@Coren @Mikel-すべての人がGNUを持っているわけではありませんfindfindOS X上とbusyboxのベースのシステムでは、と私はその数を台無しだろう、その中に改行で任意のBSDベースのシステムの番組名を推測します。
ショーンJ.ゴフ

え? wc -l改行をカウントしています。だから我々はしたい、それは改行を持っています。
ミケル

11

主にLinuxカーネルのバージョンに依存します。

次を実行することにより、システムの制限を確認できるはずです。

getconf ARG_MAX

これは、シェルによって展開された後のコマンドラインの最大バイト数を示します。

Linux <2.6.23では、制限は通常128 KBです。

Linux> = 2.6.25では、制限は128 KBまたはスタックサイズの1/4(を参照ulimit -s)のいずれか大きい方です。

詳細については、execve(2)のマニュアルページを参照してください。


残念なことに、ls *.txt制限はシェルではなくオペレーティングシステムにあるため、パイピングは問題を解決しません。

シェルはを展開し*.txt、呼び出しを試みます

exec("ls", "a.txt", "b.txt", ...)

一致するファイルが非常に多いため*.txt、128 KBの制限を超えています。

あなたは次のようなことをしなければなりません

find . -maxdepth 1 -name "*.txt" | wc -l

代わりに。

(改行を含むファイル名については、以下のショーンJ.ゴフのコメントを参照してください。)


回答に投票できなかったため申し訳ありません。もっと評判が必要です。:(ありがとうございました!!

最後の行で何.-maxdepth 1平均が説明できますか?ありがとう!:D
ギルヘルメサロメ

2
@GuilhermeSalomé .は現在のディレクトリを-maxdepth 1意味し、サブディレクトリを検索しません。これは、と同じファイルに一致するように意図されていました*.txt
ミケル

9

別の回避策:

ls | grep -c '\.txt$'

にもかかわらずls以上の出力生成ls *.txt生成(または生成する試みを)あなたが渡していないので、それは、「長すぎる引数」に問題を実行していない任意の引数をlsgrepは、ファイル一致パターンではなく、正規表現を使用することに注意してください。

あなたが使用することがあります:

ls -U | grep -c '\.txt$'

(お使いのバージョンがlsこのオプションをサポートしていると仮定します)。これはls出力をソートしないように指示し、時間とメモリの両方を節約できます。この場合、ファイルをカウントしているだけなので、順序は関係ありません。通常、出力のソートに費やされるリソースは重要ではありませんが、この場合、非常に多くの*.txtファイルがあることがすでにわかっています。

そして、単一のディレクトリにあまり多くないように、ファイルの再編成を検討する必要があります。これは実行可能である場合とそうでない場合があります。


1

MAX_ARG_PAGESはカーネルパラメーターのようです。findand を使用することxargsは、この制限に対処するための一般的な組み合わせですが、それが機能するかどうかはわかりませんwc

の出力をfind . -name \*\.txtファイルにパイピングし、そのファイル内の行をカウントすることは、回避策として役立ちます。


lsの出力で何でもできますが、これは解決しません。* .txtワイルドカードが制限を超えて展開されている限り、ls出力を開始して生成する前に失敗します。
マナトワーク

確かに、答えを更新しました。
ブラム

より良い。ただし、これを置き換えるには、サブディレクトリを再帰的にスキャンしないようにls指定-maxdepth 1する必要があります。
マナトワーク

回答に投票できなかったため申し訳ありません。もっと評判が必要です。:(

0

これは汚れているかもしれませんが、私のニーズと私の能力の範囲内で機能します。私はそれが非常に迅速に実行されるとは思わないが、それは私が私の一日を続けることができました。

ls | grep jpg | <something>

私は90,000の長いjpgのリストを取得し、それらをavconvにパイプしてタイムラプスを生成していました。

以前はls * .jpg |を使用していました この問題に遭遇する前にavconv。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.