Bashコマンドラインと入力制限


90

入力の長さについて、bash(または他のシェル)に課せられたある種の文字制限はありますか?もしそうなら、その文字制限は何ですか?

つまり、コマンドラインで実行するには長すぎるコマンドをbashで記述できますか?必要な制限がない場合、推奨される制限はありますか?


2
入力制限は非常に異なっているOSレベルの引数の上限(このような環境変数として引数以外のいくつかのものが、また1つの方に適用されます)。オペレーティングシステムに渡される生成されたコマンドは、それを生成したシェルコマンドよりも多くの文字または少ない文字を持つことができます。
チャールズ・ダフィー

回答:


125

コマンドラインの長さの制限は、シェルではなく、オペレーティングシステムによって課されます。この制限は通常、100キロバイトの範囲です。POSIXはこの制限ARG_MAXを示し、POSIX準拠システムではクエリを実行できます

$ getconf ARG_MAX    # Get argument limit in bytes

たとえば、Cygwinではこれは32000であり、私が使用しているさまざまなBSDおよびLinuxシステムでは、131072から2621440の範囲です。

この制限を超えるファイルのリストを処理する必要がある場合xargsは、を超えない引数のサブセットを使用してプログラムを繰り返し呼び出すユーティリティを確認することをお勧めしますARG_MAX

特定の質問に答えるために、はい、引数リストが長すぎるコマンドを実行しようとする可能性があります。シェルは「引数リストが長すぎます」というメッセージでエラーになります。

プログラムへの入力(stdinまたはその他のファイル記述子で読み取られる)は制限されないことに注意してください(使用可能なプログラムリソースによってのみ)。したがって、シェルスクリプトが文字列を変数に読み込む場合、によって制限されることはありませんARG_MAX。この制限は、シェルビルトインにも適用されません。


良い答えですが、説明が必要です。コンストラクトを取得しcmd <<< "$LONG_VAR"、LONG_VAR値が制限を超えた場合、コマンドが失敗しますか?
クシシュトフ・ジャブロンスキー

1
@KrzysztofJabłoński可能性は低いです。内容がLONG_VARstdinに渡されるためです。これは、完全にシェルで行われます。の引数として展開されないcmdため、fork()/ exec()のARG_MAX制限は機能しません。自分で試すのは簡単です。ARG_MAXを超える内容の変数を作成して、コマンドを実行します。
イェンス

2
記録のために、ここに説明があります:8メガバイトのm4aファイルについて、私はしました:blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null。エラーがないことに注意してください。
マイクS

3
少し注意が必要です。環境変数もカウントされます。 sysconfのマンページ > exec(3)の引数スペースのどれだけがユーザーの環境変数によって消費されるかが指定されていないため、ARG_MAXを使用することは困難です。
Gerrit

3
@ user188737バグのかなり大きな警告だと思います。たとえばxargs、macOS 10.12.6では、1つexec()に入れようとする量がに制限されていARG_MAX - 4096ます。したがってxargs、誰かが環境に多くのものを置くまで、スクリプトを使用すると機能する可能性があります。今これに遭遇しています(:)で回避してくださいxargs -s ???
ニューラルマー2018

44

わかりました、住人。ですから、私はかなり前から、コマンドラインの長さの制限を福音として受け入れてきました。それで、自分の仮定をどうするか?当然-それらを確認してください。

私は自由に使えるFedora22マシンを持っています(つまり、Linuxとbash4)。それぞれ18文字の長さの500,000個のiノード(ファイル)を含むディレクトリを作成しました。コマンドラインの長さは9,500,000文字です。このように作成されました:

seq 1 500000 | while read digit; do
    touch $(printf "abigfilename%06d\n" $digit);
done

そして私達は注意します:

$ getconf ARG_MAX
2097152

ただし、これは可能です。

$ echo * > /dev/null

しかし、これは失敗します:

$ /bin/echo * > /dev/null
bash: /bin/echo: Argument list too long

forループを実行できます:

$ for f in *; do :; done

これは別のシェル組み込みです。

状態に関するドキュメントをARG_MAX注意深く読んでください。exec関数への引数の最大長。つまりexec、を呼び出さなくても、ARG_MAX制限はありません。したがって、シェルビルトインがによって制限されない理由を説明しARG_MAXます。

実際、ls引数リストの長さが109948ファイル、つまり約2,089,000文字(ギブまたはテイク)であれば、ディレクトリを作成できます。ただし、18文字のファイル名ファイルをもう1つ追加すると、引数リストが長すぎるというエラーが発生します。したがってARG_MAX、宣伝どおりに機能ARG_MAXしています。execは、引数リストに複数の文字が含まれているため失敗しています。これには、環境データも含まれます。


うーん。ビルトインが問題の制約の対象であることを示唆する既存の回答を読んでいませんでしたが、誰かがどのようにできるかは確かにわかります。
チャールズ・ダフィー

6
はい、特に新しいコマンドライン愛好家にとっては、bashビルトインを呼び出す状況とコマンドをフォーク/実行する状況が非自明な方法で異なることを覚えておくのは難しいと思います。私はそれを明確にしたかった。(Linux Sysadminとして)就職の面接で必ず受ける質問の1つは、「ディレクトリにたくさんのファイルがあります。それらすべてをループするにはどうすればよいですか...」という質問です。質問者は常に行に向かっています。長さの制限があり、find / whileまたはxargsソリューションが必要です。将来的には、「ああ、forループを使用するだけです。それを処理できます!」と言うつもりです。:-)
マイクS

@MikeSは、forループを実行できますが、find-xargsコンボを使用できる場合は、フォークが大幅に少なくなり、高速になります。;-)
Lester Cheung

4
@LesterCheungfor f in *; do echo $f; doneはまったくフォークしません(すべてのビルトイン)。したがって、find-xargsコンボが高速になるかどうかはわかりません。テストされていません。確かに、私はOPの問題セットが何であるかを知りません。find /path/to/directoryファイルのパス名が返されるため、おそらく彼には役に立たないでしょう。多分彼はfor f in *ループの単純さが好きです。とにかく、会話はライン入力の制限についてであり、効率ではありません。それでは、コマンドラインの長さに関係するトピックにとどまりましょう。
マイクS

FWIW、私が覚えているように、問題はCでシェルを書き込もうとしていて、入力を許可する期間を決定することでした。
デレク・ハルデン2017

-3

1024のようなバッファ制限があります。読み取りは単に貼り付けまたは入力の途中でハングします。これを解決するには、-eオプションを使用します。

http://linuxcommand.org/lc3_man_pages/readh.html

-e Readlineを使用して、インタラクティブシェルで行を取得します

読み取りをread-eに変更すると、煩わしい行入力のハングがなくなります。


1
これは、read「つまり、コマンドラインで実行するには長すぎるコマンドをbashで記述できるか」ということではありません。
チャイT.レックス

@ ChaiT.Rexはある程度正しいですが、ここに問題があります。Readlineを使用せずにBashをインタラクティブに実行してみてください。つまりbash --noediting、新しいプロンプトでコマンドを実行してみてくださいecho somereallylongword。ここで、somereallylongwordは4090文字より長くなります。Ubuntu 18.04で試してみたところ、単語が切り捨てられたため、明らかにReadlineが有効になっていないことが関係しています。
アミール

@アミールおもしろい!あなたは正しいです!答えを編集しようとしましたが、このコンテキストでは-eオプションがbashに適用されないことに気付きました(bashでは、エラーが発生するとすぐにシェルを終了します)。そして、なぜパウロが本を読むためにピボットしたのかわかりません。とにかく、bashが--noreadlineで開始される場合、4〜5000文字のバッファー制限があります。それは私が知らなかった、または予期していなかった副作用です。
マイクS
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.