xargsで雑に
アドベントカレンダーの一日目だけど特にネタがない。
最近、開発用に雑にスクリプトを書く機会があり、その際にわりとxargsが役に立ったのでメモをする。
ファイル操作に関してはfind
コマンドの-exec
、テキスト加工などはawk
で済んでしまうことが多いが、
それぞれのツールを使いこなせなくても雑に書けるという点でxargsは優れていると思う。
便利オプション
自前のMacでしか使わないので、Linuxのxargsと体系が異なるかもしれない。
よく使うオプションだけ。
-I
/-J
標準入力から受け取った文字列をその後の文字列に置換して展開する。
わりと一番使う気がする。
$ seq 5 | xargs -I_ echo seq=_
seq=1
seq=2
seq=3
seq=4
seq=5
こんな感じでawkとか使わなくてもecho
で雑に文字列を加工できる。
-t
実行前に、実行するコマンドを標準エラーに出す
$ seq 5 | xargs -t -I_ echo seq=_
echo seq=1
seq=1
echo seq=2
seq=2
echo seq=3
seq=3
echo seq=4
seq=4
echo seq=5
seq=5
実行するコマンドを確認するときに便利。
-p
実行するコマンドを1行1行確認する。
$ seq 5 | xargs -p -I_ touch _.txt
touch 1.txt?...y
touch 2.txt?...n
touch 3.txt?...y
touch 4.txt?...y
touch 5.txt?...y
$ ls
1.txt 3.txt 4.txt 5.txt
y/n
で実行するか確認する。雑にツールを作るときとかに便利
-o
これはわりと最近追加されたやつっぽい。
標準入力を/dev/tty
として新しく開ける
$ seq 10 | xargs -I_ touch _.txt
$ find . -type f | xargs rm -i
remove ./5.txt? remove ./4.txt? remove ./3.txt? remove ./2.txt? remove ./1.txt?
$ ls
1.txt 2.txt 3.txt 4.txt 5.txt
$ find . -type f | xargs -o rm -i
remove ./5.txt? y
remove ./4.txt? n
remove ./3.txt? y
remove ./2.txt? y
remove ./1.txt? y
$ ls
4.txt
上記は-p
でも同じような事ができるが、rm -i
のような標準入力を必要とするプロセスに対して標準入力を送る際に便利
-P
同時に実行する数を指定できる。デフォルトは1なので、並列数を増やせる。
$ time seq 5 | xargs -I_ sleep 1 && echo _
seq 5 0.00s user 0.00s system 63% cpu 0.004 total
xargs -I_ sleep 1 0.00s user 0.01s system 0% cpu 5.029 total
$ time seq 5 | xargs -P 5 -I_ sleep 1 && echo _
seq 5 0.00s user 0.00s system 69% cpu 0.003 total
xargs -P 5 -I_ sleep 1 0.00s user 0.01s system 0% cpu 1.006 total
使い方メモ
マージ済みのbranchを消すやつ
-p
を使って都度聞くようにする
$ git branch --merged | grep -vE '^\*|master$|develop$' | xargs -p -I _ git branch -d _
git branch -d *** ?...y
git branch -d *** ?...y
git branch -d *** ?...y
常時稼働のプロセスを同時に起動する
サーバや常時稼働のプロセスを同時に起動して同時に閉じたい際、
&
でやるといちいちPIDを探してkillするのが面倒なので-P
を使って同時に起動してまとめて落とせるようにする。
下は他のpodにポートフォワーディングした状態でサーバを起動するやつ。
今まではk9sで都度接続していたけど、マイクロサービスのコンポーネント分接続するのも面倒だった。
kubefwdだとportforwardするやつ全部に同じlabel付けないとnamespace内全部に繋いでしまうし、
kube-forwarderはプリセットみたいなのを作れないっぽいので、
結局Makefileに↓みたいなのを書いた。
$ echo \
"kubectl port-forward svc/***-service 15001:15001" \
"kubectl port-forward svc/***-service 15002:15001" \
"go run server.go" \
| rs 3 | xargs -P 3 -I _ sh -c _
Forwarding from 127.0.0.1:15001 -> 15001
Forwarding from [::1]:15001 -> 15001
Forwarding from 127.0.0.1:15002 -> 15001
Forwarding from [::1]:15002 -> 15001
____ __
/ __/___/ / ___
/ _// __/ _ \/ _ \
/___/\__/_//_/\___/ v4.0.0
High performance, minimalist Go web framework
https://echo.labstack.com
____________________________________O/_______
O\
⇨ http server started on [::]:8080
各コマンドが子プロセスとして動くのでCtrl+C
でまとめて終了させれて便利。
$ ps
65027 ttys000 0:00.00 /bin/sh -c echo \011"kubectl port-forward svc/***-service 15001:15001" \011"kubectl port-forward svc/***-service
65028 ttys000 0:02.27 go run server.go
65031 ttys000 0:00.00 xargs -P 2 -I _ sh -c _
65032 ttys000 0:00.17 kubectl port-forward svc/***-service 15001:15001
65033 ttys000 0:00.17 kubectl port-forward svc/***-service 15002:15001
webpack --watch
とAPIサーバを1つのプロンプトで同時に起動したいときとかもわりと使う。