すべての引数を含むコマンドをすぐに実行するには、xargsをどのように指定しますか?

すべての引数を含むコマンドをすぐに実行するには、xargsをどのように指定しますか?

xargs-n各コマンド実行の最大引数数を指定するオプションがあります。

xargs指定されたすべての引数を含むコマンドを常にすぐに実行するように指定する方法はありますか? (すべての引数を使用せずにコマンドを直接実行するのと同じように、xargsコマンドラインの長さに対するシステム制限による失敗を回避するわけではありません)

以下は私の問題ではありません。注意が気になる場合は無視してください。 私は改行文字を削除して後続のコマンド置換を使用したくないので、代わりに使用することNULを検討しています。xargsただし、複数の実行のパラメータをグループ化したくありません。xargsこれは、xargsが実行するコマンドによって、さまざまなパラメータサブセットを使用した複数の実行の結果が、すべてのパラメータを使用した単一の実行の結果と異なる可能性があるためです。それで、xargs常にすべてのパラメータを同時に実行するように言いたいと思います。

答え1

私はまだあなたがしていることを理解していませんが、-xオプション(「コマンドラインが正しくない場合は終了」)と大きな値(システム制限より大きい)に設定されたオプションを-n組み合わせた場合は、次のことを行う必要があります。

a)xargs引数の数に関係なく一度だけ実行します。

b) オペレーティング・システムまたは xargs 内部制限のために単一のコマンドに引数を入れることができない場合、エラーが発生します。

例:

$ seq 1 10000 | xargs -n 100000000 -x sh -c 'echo "$#"' sh
10000
$ seq 1 100000 | xargs -n 100000000 -x sh -c 'echo "$#"' sh
xargs: argument list too long

残念ながら、これはBSDやSolaris xargsでは機能しません。 * BSDでこの-xオプションを使用すると、xargsそのコマンドは終了せずに単一の引数で実行されます。

fz11_2$ jot 10000 1 | xargs -n 10000 -x sh -c 'echo $#' sh | head -3
1
1
1
xargs: sh: terminated with signal 13; aborting

とんでもない小さなパラメータだけが-sトリガされます-x

fz11_2$ jot 10000 1 | xargs -s 19 -n 10000 -x sh -c 'echo $#' sh | head -3
xargs: insufficient space for arguments

これ基準GNU xargsの動作と一致しているようです。

-n  number
      Invoke utility using as many standard input arguments as
      possible, up to number (a positive decimal integer) arguments
      maximum. Fewer arguments shall be used if:
      + The command line length accumulated exceeds the size specified
        by the -s option (or {LINE_MAX} if there is no -s option).
      + The last iteration has fewer than number, but not zero,
        operands remaining.
-x
      Terminate if a constructed command line will not fit in the
      implied or specified size (see the -s option above).

答え2

あなたが説明する内容は既にデフォルトです。 xargs -n使用する引数の最大数を指定しますが、指定しない場合は、xargsできるだけ多くの引数が使用されます。

ご質問にはシステムの制限事項が記載されていますが、これを回避したくない場合や回避する必要はありません。 xargsこのシステム制限は考慮されますが、--max-chars()オプションの-s使用法で説​​明されているように、より低い値を使用することもできます。

 --max-chars=max-chars
 -s max-chars

最もよく使う 最大文字数コマンドと初期引数と引数文字列の終わりの終了null値を含む、コマンドラインあたりの文字数。許容される最大値はシステムによって異なり、execのパラメータ長制限から環境サイズ、2048バイトの余白を引いたものとして計算されます。 値が128KiBより大きい場合、128KiBがデフォルトとして使用されます。それ以外の場合、デフォルトは最大値です。 1KiBは1024バイトです。

(強調は私のもの)

何かを確認できますecho | xargs --show-limits。出力例:

Your environment variables take up 3712 bytes
POSIX upper limit on argument length (this system): 2091392
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2087680
Size of command buffer we are actually using: 131072
Maximum parallelism (--max-procs must be no greater): 2147483647

これは、私のハード制限が2087680(2MiBの直下)であることを示しています。システムが128K以上を許可している場合xargs -s 2087680(自分の制限に合わせて調整)を使用して分割を防ぐことができます。

以前のバージョンでは、オペレーティングシステムxargsが許可するよりも高い制限を提供することがあります。 4.4.2 では警告が表示されますが、指定された値は関係なく許可され、コマンドを直接実行すると表示されるのと同じエラーが発生します。

$ seq 1 2000000 | xargs -s 2100000 echo | wc -l
xargs: value for -s option should be < 2092927
xargs: echo: Argument list too long
0

ただし、バージョン4.6では、ハード制限が準拠しています。

$ seq 1 2000000 | xargs -s 2100000 echo | wc -l
xargs: value for -s option should be <= 2091392
23

答え3

いくつかの説明:

存在する

cmd1 $(cmd2)

出力結果は次のとおりですcmd2

  • ではbashNULが削除されます。他のシェルとのYMMV(zsh一部のシェルは、保存されている場合は最初のNUL以降のすべてを無視します)。
  • 末尾の改行が削除されます。
  • 結果は、$IFSほとんどのシェルのデフォルト値に基づいてSPC、TAB、NLですzsh
  • すべての操作はワイルドカードの影響を受けます(除くzsh)。たとえば、*現在のディレクトリに隠されていないファイルのリストになります。
  • 結果リストは、環境と組み合わせたリストが大きすぎる場合(Linuxのcmd1場合、execve()単一の引数が128KiBより大きい場合)、この操作を実行するシステム呼び出しが失敗します。

存在する

cmd2 | xargs cmd1

出力結果は次のとおりですcmd2

  • 一部の実装では、この出力のバイトが文字として解釈されます。たとえば、UTF-8文字セットを使用するロケールでは、e2 80 86バイトシーケンスはU + 2006文字を構成します。1人あたり6人が利用できるスペース文字、通常は空白文字として扱われます。一部のバイトが有効な文字を形成しない場合、実装によっては削除されるか、エラーが発生する可能性があります。入力がテキストでない場合、POSIXはこの動作を指定しません。
  • NULバイトがある場合、これはテキストではないため、実装によって動作が異なります。
  • LINE_MAX(一部のシステムでは1024個まで低くなる可能性があります)よりも行が多い場合でも動作は指定されません。
  • xargs予想される形式に従って入力を解析します。この形式では、スペースと改行は区切り文字として理解されます(したがって、末尾の改行は等しく分割されます)。そのリストは実装(場合によってはU + 2006を含む)によって異なり、を使用し、バックスラッシュはこれを防ぐための引用演算子として機能'...'します。"..."対応する区切り記号およびその他の引用演算子は特別に扱われます。
  • 結果はリストまたは性格
  • いくつかの実装では、これらの単語のいずれかであれば、ファイルの終わりの論理_インジケータとして扱われ、その後のすべての内容は無視されます。
  • これらの単語のいずれかが特定の制限(多くのシステムでは約255バイト)を超える場合、動作は指定されません。
  • 残りの単語は引数として渡されますが、リストが大きすぎるcmd1場合は、コマンドの代替ケースのように失敗するのではなく、成功するためにできるだけxargs多くの単語(実装に応じて少し余裕があります)を合わせて実行します。execve()すべてのパラメータを使用するために必要なだけコマンドを実行します。

今:

  • cmd2出力全体をパラメータとして渡す場合cmd1
    • その出力にNUL文字が含まれている場合は、コマンドのexecve()置き換えやxargs
    • その出力がARG_MAX制限より大きい場合はそれを行うことはできません(一部のシステムではその制限を増やす方法があります)exexve()。たとえば、cmd1シェルの組み込み機能や機能を使用できます(そのexecve()場合は関係ありません)。ただし、実際にはzshこの場合でも NUL を含むパラメーターのみがサポートされます。
    • Linuxでは、128KiBを超えると不可能です。この制限は増やすことはできません。
    • そうでない場合(NULがなく、十分に小さい場合)、いつでも次のことを行うout=$(cmd2; echo .); cmd1 "${out%.}"か、GNUを使用できますxargscmd2 | xargs -0 cmd1

関連情報