つなぐ

INPUT · スライド

流れを引数に変える(`xargs`)

01 / 08

パイプでは渡せない相手がいる

ここまでパイプで何でもつなげてきたけれど、うまくいかない相手がいるんだ。

```
find . -name '*.tmp' | rm # ✗ 何も消えない
```

理由は rm の作りにあるよ。rm入口(標準入力)を読まないんだ。消すものは引数で受け取る決まりなんだよ。

```
rm furui/a.tmp furui/b.tmp # ◯ 引数で渡す
```

流れてきた文字を、引数の形に変えて渡す。それをするのが xargs だよ。

02 / 08

入口を読む道具・読まない道具

ここで道具を2種類に分けて覚えよう。

入口を読む道具(パイプでそのまま渡せる)

  • grep sort wc head tail uniq tr less tee

引数しか受け取らない道具xargs が要る)

  • rm cp mv mkdir touch chmod echo

見分け方があるよ。ファイルを操作する道具は引数側中身を加工する道具は入口側だよ。

名前を扱う仕事(消す・作る・動かす)には xargs。中身を扱う仕事(探す・数える・並べる)にはパイプだけ。そう覚えるといいよ。

03 / 08

`xargs` の仕事はひとつ

xargs がやることは1つだけだよ。入口から受け取った文字を、うしろに書いたコマンドの引数として並べる

```
~ $ echo a.txt b.txt | xargs touch
(= touch a.txt b.txt を実行した)
```

改行も空白も区切りとして扱うので、findls の出力(1行1件)をそのまま渡せるよ。

```
find . -name '*.tmp' | xargs rm
```

見つけたものを全部消す、というのがこれで書けるんだ。

~ $ find . -name '*.tmp'./furui/a.tmp./furui/b.tmp~ $ find . -name '*.tmp' | xargs rm

04 / 08

まとめて渡す・1つずつ渡す

xargs は既定ではできるだけまとめて渡すよ。100個あっても1回のコマンドで渡そうとするんだ(そのほうが速いからね)。

1つずつにしたいときは -n1 だよ。

```
~ $ echo a b c | xargs echo
a b c ← 1回で渡した
~ $ echo a b c | xargs -n1 echo
a
b
c ← 3回に分けた
```

-n2 なら2つずつ。渡す個数を決められるんだ。

05 / 08

`-I{}` で置き場所を決める

xargs はふつううしろに付け足す形で渡すよ。でも「真ん中に入れたい」ことがあるんだ。

```
cp ファイル ファイル.bak
```

これは同じ名前を2か所に書きたいよね。そのときは -I{} を使うよ。

```
ls *.txt | xargs -I{} cp {} {}.bak
```

{} が受け取った1行に置き換わるんだ。-I を使うと自動で1行ずつになるよ(-n1 と同じ扱い)。

{} という書き方は find -exec と同じだね。覚えることが1つ減るよ。

06 / 08

`-t` で何を実行するか見る

xargs は怖い道具だよ。rm と組み合わせるとまとめて消えるからね。

だから打つ前に確かめる方法を覚えよう。-t を付けると、実行するコマンドを見せてから動くんだ。

```
find . -name '*.tmp' | xargs -t rm
rm ./furui/a.tmp ./furui/b.tmp ← これを実行するよ、という表示
```

もっと安全なのは、まず xargs を付けずに find だけ打つことだよ。出てきた一覧が消したいものだけなら、そこで初めて | xargs rm を足す。

確かめてから消す。この順番は一生使う習慣になるよ。

07 / 08

空白の入った名前に気をつける

xargs には弱点があるよ。空白を区切りとして見るので、名前に空白があると壊れるんだ。

```
~ $ ls
sp ace.txt
~ $ ls | xargs wc -c
wc: sp: No such file or directory
wc: ace.txt: No such file or directory
```

sp ace.txt が2つの名前だと思われてしまったね。

直し方は決まっているよ。find-print0xargs-0 を付けるんだ。区切りを空白ではなく見えない文字(NUL)にする指示だよ。

```
find . -name '*.txt' -print0 | xargs -0 wc -c
```

おまじないに見えるけれど、空白入りの名前を扱うときの決まり文句として覚えておいて。

08 / 08

さあ、打ってみよう

furui の中に .tmp ファイルが2つ入っているよ。消す練習に使うよ(この環境のホームは問題ごとに作り直されるので、安心して消してね)。

iremono.txt には harunatsuaki と書いてあるよ。これを使って入れ物をまとめて作る練習をするよ。

xargs は覚えることが少ないけれど、組み合わせると効き目が大きい道具だよ。「探して、まとめて処理する」がこれでできるようになるんだ。