入力の長さについて、bash(または他のシェル)に課せられたある種の文字制限はありますか?もしそうなら、その文字制限は何ですか?
つまり、コマンドラインで実行するには長すぎるコマンドをbashで記述できますか?必要な制限がない場合、推奨される制限はありますか?
回答:
コマンドラインの長さの制限は、シェルではなく、オペレーティングシステムによって課されます。この制限は通常、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値が制限を超えた場合、コマンドが失敗しますか?
LONG_VAR
stdinに渡されるためです。これは、完全にシェルで行われます。の引数として展開されないcmd
ため、fork()/ exec()のARG_MAX制限は機能しません。自分で試すのは簡単です。ARG_MAXを超える内容の変数を作成して、コマンドを実行します。
blah="$(cat /home/schwager/Music/Recordings/20090420\ 131623.m4a)"; cat <<< $blah >/dev/null
。エラーがないことに注意してください。
xargs
、macOS 10.12.6では、1つexec()
に入れようとする量がに制限されていARG_MAX - 4096
ます。したがってxargs
、誰かが環境に多くのものを置くまで、スクリプトを使用すると機能する可能性があります。今これに遭遇しています(:)で回避してくださいxargs -s ???
。
わかりました、住人。ですから、私はかなり前から、コマンドラインの長さの制限を福音として受け入れてきました。それで、自分の仮定をどうするか?当然-それらを確認してください。
私は自由に使える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は、引数リストに複数の文字が含まれているため失敗しています。これには、環境データも含まれます。
for f in *; do echo $f; done
はまったくフォークしません(すべてのビルトイン)。したがって、find-xargsコンボが高速になるかどうかはわかりません。テストされていません。確かに、私はOPの問題セットが何であるかを知りません。find /path/to/directory
ファイルのパス名が返されるため、おそらく彼には役に立たないでしょう。多分彼はfor f in *
ループの単純さが好きです。とにかく、会話はライン入力の制限についてであり、効率ではありません。それでは、コマンドラインの長さに関係するトピックにとどまりましょう。
1024のようなバッファ制限があります。読み取りは単に貼り付けまたは入力の途中でハングします。これを解決するには、-eオプションを使用します。
http://linuxcommand.org/lc3_man_pages/readh.html
-e Readlineを使用して、インタラクティブシェルで行を取得します
読み取りをread-eに変更すると、煩わしい行入力のハングがなくなります。
read
「つまり、コマンドラインで実行するには長すぎるコマンドをbashで記述できるか」ということではありません。
bash --noediting
、新しいプロンプトでコマンドを実行してみてくださいecho somereallylongword
。ここで、somereallylongwordは4090文字より長くなります。Ubuntu 18.04で試してみたところ、単語が切り捨てられたため、明らかにReadlineが有効になっていないことが関係しています。