xargs入門|パイプの結果を次のコマンドの引数に渡す基本

xargs入門|パイプの結果を次のコマンドの引数に渡す基本

「このファイル一覧、まとめて消したいだけなのに」と思って、find の結果を rm に渡そうとしてうまくいかず、戸惑ったことはないでしょうか。

実は rm や cp のようなコマンドは、パイプで流し込んだ文字列(標準入力)を「処理する対象」として受け取ってくれません。

この「パイプの出力を、次のコマンドの引数に変換する」役目を担うのが xargs です。

この記事では、xargs の基本と、実務で必ずぶつかる落とし穴までを、コピペで試せる形で整理します。

xargs とは何か(パイプとの違い)

パイプ(|)は、左のコマンドの出力を右のコマンドの標準入力へ流し込む仕組みです。

grep のように標準入力を読むコマンドは動きますが、rm・cp・kill などは「引数」でしか対象を受け取りません。

xargs は標準入力から受け取った文字列を、指定したコマンドの引数へ組み替えて実行します。

引数のコマンドを省略すると、xargs は既定で echo を実行するのです。

echo "a b c" | xargs
# → a b c (echo が実行される)

基本の使い方

標準入力を引数として渡す

一番よく使うのは、find の結果を別コマンドへ渡す形です。

find . -name "*.tmp" | xargs rm
# 見つかった .tmp ファイルをまとめて削除

find … | rm では動かなかった処理が、xargs を挟むだけで通ります。

-n で1回に渡す個数を絞る

-n を付けると、コマンド1回あたりに渡す引数の数を制限できるわけです。

echo 1 2 3 4 | xargs -n 2 echo
# → 1 2
#   3 4  (2個ずつ echo が2回動く)

-I で引数を差し込む位置を指定する

引数を行末ではなく途中に置きたいときは、-I で置換文字列を決めます。

ls *.txt | xargs -I {} mv {} {}.bak
# 各 .txt を .txt.bak にリネーム({} が1行ずつ入る)

-I を使うと、入力1行ごとに1回コマンドが実行される点も押さえておきたいところです。

実務で効くオプション

-0 でスペース入りファイル名を守る

xargs は既定で空白と改行を区切りとして扱うため、スペースを含むファイル名では壊れます。

find の -print0 と xargs の -0 を組み合わせ、区切りをヌル文字にするのが定石です。

find . -name "*.log" -print0 | xargs -0 rm
# ファイル名に空白があっても安全に削除

xargs を使うなら -print0 と -0 をセットで、と覚えておくと事故がぐっと減ります。

-P で並列実行する

-P に数字を渡すと、複数のコマンドを同時に走らせて処理を速められるのです。

find . -name "*.png" -print0 | xargs -0 -P 4 -I {} cwebp {} -o {}.webp
# 4並列で画像を変換

CPU を使い切れる一方、複数プロセスの出力が入り混じる点だけは頭の片隅に置いておきたいですね。

-t で実行前にコマンドを確認する

-t を付けると、実際に走らせるコマンドを標準エラーへ表示してから実行します。

find . -name "*.bak" | xargs -t rm
# 実行するコマンドを表示してから削除

消す前に中身を確かめたいときは、まず rm を echo に差し替えて空撃ちするのも安全です。

find・grep との合わせ技

xargs が最も輝くのは、find で集めて grep で探す、という連携。

find . -name "*.js" -print0 | xargs -0 grep -n "TODO"
# JSファイルを横断して TODO の行番号を洗い出す

find 側の細かい絞り込みは、こちらの記事にまとめています。

findコマンド入門|ファイルを名前・種類・更新日で探す基本

よくある落とし穴

入力が空でも、GNU 版の xargs は既定でコマンドを1回実行してしまうのです。

空なら何もしたくない場合は、-r(–no-run-if-empty)を付けて空実行を止めます。

find . -name "*.none" | xargs -r rm
# 対象が0件なら rm を呼ばない

もう一つ、引数が多すぎてもエラーにはならず、xargs が自動でコマンドを複数回に分割してくれる点は、覚えておくと安心です。

最後に

xargs は「パイプの出力を引数に変える」一点さえ掴めば、find や grep との組み合わせで一気に手数が減ります。

まずは rm の前に xargs echo で空撃ちして、渡される引数を目で確かめるところから始めるのが安全でしょう。

以上です。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

CAPTCHA