このxargs
命令はいつも私を混乱させます。一般的なルールがありますか?
次の 2 つの例を考えてみましょう。
$ \ls | grep Cases | less
「Cases」に一致するファイルを印刷しますが、コマンドを次に変更するには、次のものがtouch
必要ですxargs
。
$ \ls | grep Cases | touch
touch: missing file operand
Try `touch --help' for more information.
$ \ls | grep Cases | xargs touch
答え1
違いは、ターゲットプログラムが許可するデータにあります。
パイプのみを使用すると、標準入力ストリーム(STDIN)のデータを生データの束として受け取り、一度に1行ずつ並べ替えることができます。ただし、一部のプログラムは標準入力のコマンドを受け入れず、そのコマンドの引数にそのコマンドが指定されることを期待しています。たとえば、touch
次のようにコマンドラインからファイル名を引数として渡しますtouch file1.txt
。
ファイル名を出力するプログラムがある場合標準出力そしてそれらを使いたいパラメータとしてこれを行うには、それをtouch
使用xargs
してSTDINストリームデータを読み取り、各行をコマンドの空白で区切られた引数に変換する必要があります。
これら2つは同じです。
# touch file1.txt
# echo file1.txt | xargs touch
xargs
その機能が何であるか、なぜ必要なのかを正確に知らない限り、使用しないでください。多くのxargs
場合、キャストを使用するよりも操作を実行するより良い方法があります。変換プロセスには、エスケープや単語拡張などの潜在的なトラップもあります。
答え2
すでに提供されている回答を拡張するには、xargs
今日のマルチコアおよび分散コンピューティングの世界でますます重要になっている素晴らしい仕事を実行できます。つまり、ジョブを並列に処理できます。
たとえば、
$ find . -type f -name '*.wav' -print0 |xargs -0 -P 3 -n 1 flac -V8
*.wav => *.flac()をエンコードするために、3つのプロセスが同時に使用されます-P 3
。
答え3
xargsはstdinにファイルパスのリストがあり、それに対していくつかの操作を実行したい場合に特に便利です。たとえば、
$ git ls-files "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
段階的に確認してみましょう。
$ git ls-files "*.tex"
tex/ch1/intro.tex
tex/ch1/motivation.tex
....
言い換えれば、入力は、どのようなタスクを実行したいパスのリストです。
echo
これらのパスに対してxargsが実行する操作を理解するには、次のようにコマンドを前に追加することをお勧めします。
$ git ls-files "*.tex" | xargs -n 1 echo sed -i "s/color/colour/g"
sed -i "s/color/colour/g" tex/ch1/intro.tex
sed -i "s/color/colour/g" tex/ch1/motivation.tex
....
この-n 1
パラメータを使用すると、xargsは各行を独自のコマンドに変換します。このsed -i "s/color/colour/g"
コマンドは、指定されたファイル内のすべての項目を置き換えますcolor
。colour
これはパスにスペースがない場合にのみ機能します。これを行うには、nullで終わるパスをxargsへの入力として使用するようにフラグを渡す必要があります-0
。使用例は次のとおりです。
$ git ls-files -z "*.tex" | xargs -0 -n 1 sed -i "s/color/colour/g"
上記と同じことを行いますが、いずれかのパスにスペースがある場合にも機能します。
find
これは、またはなど、ファイル名を出力として生成するすべてのコマンドに適用されますlocate
。多くのファイルがあるgitリポジトリでこれを使用している場合は、次のようなgit grep -l
代わりにこれを使用する方が効率的ですgit ls-files
。
$ git grep -l "color" "*.tex" | xargs -n 1 sed -i "s/color/colour/g"
このgit grep -l "color" "*.tex"
コマンドは、「color」というフレーズを含む「* .tex」ファイルのリストを提供します。
答え4
xargs
find
あなたの例では、必要な作業を正確に実行し、安全に実行するため、まったく使用する必要はありません。
使用したいものはまさに次のとおりですfind
。
find -maxdepth 1 -name '*Cases*' -exec touch {} +
この場合、-maxdepth 1
これはサブディレクトリに深く入らず、現在のディレクトリでのみ検索することを意味します。 maxlengthに制限されない限り、findはデフォルトですべてのサブディレクトリを検索します(通常は必要なものです)。は{}
その場所で置き換えられるファイルの名前であり、2+
つのコマンド終了タグのうちの1つです。もう一つはです;
。違いは;
、各ファイルに対してコマンドを一度実行することで、次の+
コマンドを実行することです。すべてのファイルを一度にコマンドします。ただし、シェルは自分で解釈しようとする可能性があるため、シェルを使用またはエスケープする必要があることに注意して;
ください。はい、これらの小さな迷惑がたくさんありますが、その力はそれを相殺しても残ります。\;
';'
find
どちらも最初は学ぶのが難しいですfind
。xargs
学習に役立つか、オプションを試してxargs
ください。このオプションは、実行するコマンドを表示し、実行するかどうかを尋ねるメッセージを表示します。-p
--interactive
同様に、代わりにfind
を使用してコマンドを実行するかどうかを尋ねるメッセージを表示することもできます。-ok
-exec
しかし、時にはfind
やりたいことをすべてすることができない場合がありますが、この時がxargs
必要です。この-exec
コマンドは{}
発生例を1つだけ許可するため、使用時にエラーが発生した場合はfind -type f -exec cp {} {}.bak \;
次のことができます。find -type f -print0 | xargs -0 -l1 -IX cp X X.bak
以下について詳しく学ぶことができます。コマンドの実行内部にGNU Findutils マニュアル。
また、ファイルを処理するときやオプションを使用したり、ヌル終了入力を生成したりしないと、find
問題を引き起こす可能性があるスペースやその他の文字が発生するため、必要に応じて実行するのが安全であると述べました。内容が空です。xargs
-0
--null