web-dev-qa-db-ja.com

なぜxargsが必要なのですか?

「notes.txt」という名前のファイルを除いて、ディレクトリ内のすべてのファイルを削除するとします。私はこれをパイプラインls | grep -v "notes.txt" | xargs rm。 2番目のパイプの出力がrmが使用する入力である場合、なぜxargsが必要なのですか?

比較のために、パイプラインecho "#include <knowledge.h>" | cat > foo.cは、xargsを使用せずに、エコーされたテキストをファイルに挿入します。これら2つのパイプラインの違いは何ですか?

26
seewalker

STDINと引数の2つの非常に異なる種類の入力を混乱させています。引数は、コマンドの開始時にコマンドに提供される文字列のリストです。通常、コマンド名の後に指定します(例:echo these are some argumentsまたはrm file1 file2)。一方、STDINは、コマンドの開始後に(オプションで)コマンドが読み取ることができるバイトのストリーム(場合によってはテキストでないこともあります)です。以下にいくつかの例を示します(catは引数またはSTDINのいずれかをとることができますが、引数によって異なる処理を行うことに注意してください)。

echo file1 file2 | cat    # Prints "file1 file2", since that's the stream of
                          # bytes that echo passed to cat's STDIN
cat file1 file2    # Prints the CONTENTS of file1 and file2
echo file1 file2 | rm    # Prints an error message, since rm expects arguments
                         # and doesn't read from STDIN

xargsは、STDINスタイルの入力を引数に変換するものと考えることができます。

echo file1 file2 | cat    # Prints "file1 file2"
echo file1 file2 | xargs cat    # Prints the CONTENTS of file1 and file2

echoは、実際には多かれ少なかれその逆を行います。引数をSTDOUT(他のコマンドのSTDINにパイプすることができます)に変換します。

echo file1 file2 | echo    # Prints a blank line, since echo doesn't read from STDIN
echo file1 file2 | xargs echo    # Prints "file1 file2" -- the first echo turns
                                 # them from arguments into STDOUT, xargs turns
                                 # them back into arguments, and the second echo
                                 # turns them back into STDOUT
echo file1 file2 | xargs echo | xargs echo | xargs echo | xargs echo    # Similar,
                                 # except that it converts back and forth between
                                 # args and STDOUT several times before finally
                                 # printing "file1 file2" to STDOUT.
38
Gordon Davisson

catSTDINから入力を受け取り、rmは受け取りません。このようなコマンドの場合、xargsSTDINごとに1行ずつ繰り返し、コマンドラインパラメーターを指定してコマンドを実行する必要があります。

9
Alex P.