「notes.txt」という名前のファイルを除いて、ディレクトリ内のすべてのファイルを削除するとします。私はこれをパイプラインls | grep -v "notes.txt" | xargs rm
。 2番目のパイプの出力がrmが使用する入力である場合、なぜxargsが必要なのですか?
比較のために、パイプラインecho "#include <knowledge.h>" | cat > foo.c
は、xargsを使用せずに、エコーされたテキストをファイルに挿入します。これら2つのパイプラインの違いは何ですか?
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.
cat
はSTDIN
から入力を受け取り、rm
は受け取りません。このようなコマンドの場合、xargs
をSTDIN
ごとに1行ずつ繰り返し、コマンドラインパラメーターを指定してコマンドを実行する必要があります。