web-dev-qa-db-ja.com

いつサブシェルと `xargs`を使用する必要がありますか?

xargsを使用する多くの単純なコマンドは、サブシェルを使用するコマンドとして書き直すことができます。たとえば、サブシェルとxargsを使用して記述された、/usr/binの最大の10個のバイナリを連結するために今日使用していたものを次に示します。

サブシェル:

$ cat $(du -sh /usr/bin/* | sort -h | tail | cut -d "      " -f 2 | tr "\n" " ")

xargs

$ du -sh /usr/bin/* | sort -h | tail | cut -d "      " -f 2 | tr "\n" " " | xargs cat

では、いつサブシェルを使用する必要があり、いつxargsを使用する必要がありますか?

注意:

カットの区切り文字はハードタブであり、SEでは正しく表示されないようです。

6
haneefmubarak

これは少し意見の分かれる質問ですが、私はこれを言います、それは2つのことに大きく依存しています:

  1. 実行するコマンドは何ですか?
  2. 実行するインスタンスはいくつですか?

同じプロセスを数十から数百実行する可能性が高い場合は、xargsが最も理にかなっています。また、プロセスの起動に費用がかかる場合は、xargsが最適なルートである可能性があります。

ただし、コマンドのインスタンスがほんの一握りしかない場合は、サブシェルで実行しても問題ありません。

サブシェルによって生成される引数の長さが非常に長くなる場合は、xargsを使用することをお勧めします。ただし、この制限はかなり極端で、通常は2MB〜4MBの文字であるため、これを超えることはほとんどありません。次のように確認できます。

$ xargs --show-limits < /dev/null
Your environment variables take up 4805 bytes
POSIX upper limit on argument length (this system): 2090299
POSIX smallest allowable upper limit on argument length (all systems): 4096
Maximum length of command we could actually use: 2085494
Size of command buffer we are actually using: 131072

ちなみに、これらのコマンドはどちらも機能していないようです。 cut -d " " -f2は無効です。cutは区切り文字として1文字しか使用できません。代わりにこれを試してください:

$ du -sh /usr/bin/* | sort -h | awk 'NR<=10 {print $2}' | tr "\n" " "
-or-
$ du -sh /usr/bin/* | sort -h | tail | cut -f2- | tr "\n" " "

ここでawkを使用すると、スペースを含むファイル名またはディレクトリがある場合に問題が発生する可能性があるため、注意して使用してください。

$ ll
total 0
-rw-rw-r--. 1 saml saml 0 Feb 22 19:47 file 1
-rw-rw-r--. 1 saml saml 0 Feb 22 19:47 file 2

$ du -sh * | sort -h | awk 'NR<=10 {print $2}' | tr "\n" " "
file file $

私はcut -f2-メソッドを使用しますが、それは私だけです。他の人は、より洗練されたawkソリューションを提供するかもしれませんが、最も意味のあるものを使用してください。

Awk + ​​catを使用する

注:出力をxargsにパイプする場合、catを呼び出す必要はありません。デフォルトでは、xargsは渡された出力を自動的にエコーします。

$ du -sh * | sort -h | tail | cut -f2- | tr "\n" " " | xargs
file 1 file 10 file 2 file 3 file 4 file 5 file 6 file 7 file 8 file 9

編集#1

タブを使用してカットで区切る場合、明示的に行う必要はありません。デフォルトではそのようになっています。

   -d, --delimiter=DELIM
          use DELIM instead of TAB for field delimiter
6
slm