xargsコマンドの使い方|find連携やパイプで引数を渡す実践例


図解60p「Linuxサーバー構築入門マニュアル」無料
登録10秒/自動返信でDL/合わなければ解除3秒
HOMELinux技術 リナックスマスター.JP(Linuxマスター.JP)Linuxtips > xargsコマンドの使い方|find連携やパイプで引数を渡す実践例
「findで見つけたファイルを一括で削除したいけど、パイプでうまく渡せない」
「xargsコマンドの存在は知っているけど、使い方がよくわからない」

Linuxでコマンドを組み合わせるとき、パイプ( | )だけでは引数を渡せない場面があります。そんなときに活躍するのが xargs コマンドです。標準入力から受け取ったデータを、別のコマンドの引数として渡してくれます。

この記事では、xargsコマンドの基本から、findとの連携・ファイル名にスペースを含む場合の安全な処理・並列実行まで、実務で必要になる使い方をすべて解説します。コマンドを組み合わせる力が格段に上がるので、しっかり押さえておきましょう。

なぜxargsが必要なのか?パイプだけでは解決できない問題

パイプ( | )は、前のコマンドの標準出力を次のコマンドの標準入力に渡します。grepやsortのように標準入力を処理するコマンドなら問題ありません。

しかし、rm や mkdir のように引数としてファイル名を受け取るコマンドには、パイプで直接データを渡せません。

# これはうまくいかない(rmは標準入力を読まない) find /tmp -name "*.log" | rm

ここで xargs を間に挟むと、標準入力から受け取った文字列をコマンドの引数に変換してくれます。

# xargsを挟めば、findの結果がrmの引数になる find /tmp -name "*.log" | xargs rm

つまり xargs は、「標準入力 → コマンド引数」の橋渡し役です。パイプでコマンドを繋ぐだけでは対応できない場面を解決するために存在します。

xargsコマンドの基本的な使い方

1. 基本書式を理解する

xargs の基本書式は以下のとおりです。

# 基本書式 コマンド1 | xargs コマンド2

コマンド1の出力がxargsに渡され、xargsがそれをコマンド2の引数として実行します。コマンド2を省略すると、デフォルトで echo が使われます。

# echoがデフォルトで実行される $ echo "file1 file2 file3" | xargs file1 file2 file3

2. findの結果をxargsに渡す

xargsの最も多い使い方が、findコマンドとの組み合わせです。findで検索したファイルに対して、一括で操作を実行できます。

# 30日以上前のログファイルを一括削除 find /var/log -name "*.log" -mtime +30 | xargs rm -f

# 特定ディレクトリ配下の.confファイルをすべてgrep検索 find /etc -name "*.conf" | xargs grep "Listen"

3. 引数の数を制限する(-n オプション)

デフォルトでは、xargsは受け取った引数をできるだけまとめて1回のコマンド実行に渡します。-n オプションを使うと、1回の実行で渡す引数の数を制限できます。

# 1つずつ引数を渡して実行 $ echo "file1 file2 file3" | xargs -n 1 echo file1 file2 file3

# 2つずつ引数を渡して実行 $ echo "file1 file2 file3 file4" | xargs -n 2 echo file1 file2 file3 file4

-n 1 は、ファイルごとに個別にコマンドを実行したい場合に便利です。

4. 引数の挿入位置を指定する(-I オプション)

デフォルトでは引数はコマンドの末尾に追加されますが、-I オプションを使うと、引数を挿入する位置を自由に指定できます。

# {} の位置に引数が入る find /var/log -name "*.log" | xargs -I {} cp {} /backup/logs/

この例では、findで見つかったファイルがそれぞれ {} の位置に代入されて、cp コマンドが実行されます。コマンドの途中に引数を挿入したい場合には -I が欠かせません。

-I を指定すると、自動的に -n 1 と同じ動作(1つずつ処理)になります。

実務で役立つxargsの応用テクニック

1. ファイル名にスペースや特殊文字が含まれる場合の安全な処理

xargsはデフォルトでスペース・タブ・改行を区切り文字として扱います。そのため、ファイル名にスペースが含まれていると、意図しない分割が起きます。

# 「my file.txt」が「my」と「file.txt」に分割されてしまう echo "my file.txt" | xargs rm

これを防ぐには、findの -print0 と xargs の -0 を組み合わせます。NUL文字(\0)を区切り文字にすることで、ファイル名にスペースや改行が含まれていても安全に処理できます。

# NUL区切りで安全に処理(実務の鉄則) find /data -name "*.csv" -print0 | xargs -0 rm -f

実務では、findとxargsを組み合わせるときは常に -print0 と -0 をセットで使うのが鉄則です。どんなファイル名が存在するかわからない本番環境では、この習慣が事故を防ぎます。

2. 実行前に確認する(-p オプション)

削除や移動など、取り消しができない操作を行う場合は、-p オプションで実行前に確認できます。

# 実行前に確認プロンプトを表示 find /tmp -name "*.tmp" | xargs -p rm -f rm -f /tmp/cache1.tmp /tmp/cache2.tmp ?...y

y を入力するとコマンドが実行され、それ以外のキーを押すとスキップされます。本番環境で一括削除を行う前には、まず -p で対象を確認しましょう。

3. 実行内容を表示する(-t オプション)

-t オプションを付けると、実際に実行されるコマンドが標準エラー出力に表示されます。デバッグや動作確認に便利です。

# 実行されるコマンドを表示 $ echo "file1 file2" | xargs -t rm -f rm -f file1 file2

4. 並列実行で処理を高速化する(-P オプション)

大量のファイルを処理する場合、-P オプションでプロセスを並列実行できます。CPUコアが複数あるサーバーでは、処理時間を大幅に短縮できます。

# 4プロセス並列でgzip圧縮 find /var/log/archive -name "*.log" -print0 | xargs -0 -P 4 -n 1 gzip

-P 4 は最大4プロセスを同時に実行するという意味です。-n 1 と組み合わせて、ファイルごとに独立したプロセスで処理します。

-P 0 を指定すると、可能な限り多くのプロセスを同時に起動します。ただし、サーバーの負荷が急上昇する可能性があるため、本番環境では具体的な数値を指定してください。

5. grepの検索結果に対して一括操作する

grepで特定の文字列を含むファイルを見つけ、そのファイルに対して一括で操作を行うパターンです。

# "deprecated" を含む設定ファイルを一覧表示 grep -rl "deprecated" /etc/ | xargs ls -la # 特定の文字列を含むファイルを一括でsedで置換 grep -rl "old-server" /etc/nginx/ | xargs sed -i 's/old-server/new-server/g'

grep -rl の -r は再帰検索、-l はファイル名のみ出力するオプションです。

「xargsがうまく動かない」時のトラブルシュート

1. 「argument list too long」エラーが出る

xargsを使わずに直接コマンドを実行した場合、引数が多すぎると「Argument list too long」エラーになります。

# ファイルが多すぎるとエラーになる rm /tmp/logs/*.log -bash: /bin/rm: Argument list too long

xargsを使えば、自動的に引数をOSの上限以内に分割して複数回に分けて実行してくれます。

# xargsが自動的に分割して実行してくれる find /tmp/logs -name "*.log" | xargs rm -f

2. ファイル名のスペースで意図しない動作になる

前述のとおり、xargsはデフォルトでスペースを区切り文字として扱います。ファイル名にスペースが含まれる環境では、find -print0 と xargs -0 を必ずセットで使ってください。

# スペース入りファイル名を安全に処理 find /data -type f -print0 | xargs -0 ls -la

3. xargsに渡すデータが空の場合にエラーになる

findの結果が0件のとき、xargsはデフォルトでコマンドを引数なしで実行してしまい、エラーになることがあります。--no-run-if-empty オプション(GNU xargs)を付ければ、入力が空のときはコマンドを実行しません。

# 結果が空でもエラーにならない find /tmp -name "*.bak" | xargs --no-run-if-empty rm -f

LinuxのGNU xargsでは --no-run-if-empty がデフォルトで有効になっている場合もありますが、スクリプトに明示的に書いておくと移植性が高まります。

4. xargsとfind -exec の使い分け

findコマンドには -exec オプションがあり、xargsを使わなくてもファイルごとにコマンドを実行できます。

# find -exec(ファイルごとに1回ずつコマンドを起動) find /var/log -name "*.log" -exec rm -f {} \; # xargs(引数をまとめて効率的に実行) find /var/log -name "*.log" | xargs rm -f

find -exec {} \;:ファイルごとにコマンドを1回起動する。ファイル数が多いと遅い
find -exec {} +:引数をまとめてコマンドを実行する。xargsに近い動作
xargs:引数をまとめて効率的に実行する。-P で並列処理もできる

処理速度を重視するならxargs、シンプルに書きたいなら find -exec {} + がおすすめです。

本記事のまとめ

xargsコマンドは、標準入力から受け取ったデータをコマンドの引数に変換する、パイプ処理に欠かせないコマンドです。以下の早見表で、主な使い方をすぐに確認できます。
やりたいこと コマンド
findの結果を別コマンドの引数にする find パス 条件 | xargs コマンド
1つずつ引数を渡して実行する コマンド | xargs -n 1 コマンド
引数の挿入位置を指定する コマンド | xargs -I {} コマンド {}
スペース入りファイル名を安全に処理する find パス 条件 -print0 | xargs -0 コマンド
実行前に確認する コマンド | xargs -p コマンド
並列実行で高速化する コマンド | xargs -P 4 -n 1 コマンド
grepで見つけたファイルを一括操作する grep -rl "文字列" パス | xargs コマンド
入力が空のときコマンドを実行しない コマンド | xargs --no-run-if-empty コマンド

xargsだけでなく、Linuxのコマンド連携を体系的に学びませんか?

xargsのようなコマンドの組み合わせは、サーバー管理の効率を大きく左右します。パイプやリダイレクトの仕組みを根本から理解することで、どんな場面でも応用が利くようになります。
ネットの切れ端の情報をコピペするだけでなく、現場で通用する安全なLinuxサーバー構築の「型」を体系的に身につけたい方へ、『Linuxサーバー構築入門マニュアル(図解60P)』を完全無料でプレゼントしています。

「独学の時間がもったいない」「プロから直接、現場の技術を最短で学びたい」という本気の方には、2日で実務レベルのスキルが身につく【初心者向けハンズオンセミナー】も開催しています。



無料プレゼント
図解60p「Linuxサーバー構築入門マニュアル」
独学で詰まる前に、“型(手順書)”で最初の環境構築をサクッと終わらせましょう。
登録10秒/自動返信でDL/合わなければ解除3秒
無料で受け取る ※メールアドレスだけでもOK(必須項目は最小限)

宮崎 智広

この記事を書いた人

宮崎 智広(みやざき ともひろ)

株式会社イーネットマーキュリー代表。現役のLinuxサーバー管理者として15年以上の実務経験を持ち、これまでに累計3,100名以上のエンジニアを指導してきたLinux教育のプロフェッショナル。「現場で本当に使える技術」を体系的に伝えることをモットーに、実践型のLinuxセミナーの開催や無料マニュアルの配布を通じてLinux人材の育成に取り組んでいる。

図解60pのLinux無料マニュアル
登録10秒/自動返信でDL
無料で受け取る