xargsにパイプで渡した標準入力が空だった場合におかしな動きをしないようにする
はじめに
xargs コマンドは非常に便利です。
パイプでつなぎ、前のコマンドを1つずつ(あるいはいくつかの束ずつ)処理していくときに
簡潔に記述できかつ高速です。
ただ、パイプの前のコマンドの実行結果が空になると想定しない挙動をする場合があります。
問題と対処について紹介します。
検証環境
$ uname -moi
x86_64 x86_64 GNU/Linux
$ bash -version | head -n 1
GNU bash, version 4.2.46(2)-release (x86_64-redhat-linux-gnu)
$ xargs --version | head -n 1
xargs (GNU findutils) 4.5.11
何も考慮せず "xargs" を使ってみる。
なにか具体的な例を考えたいので、 seq
コマンドで生成した数列を xargs
に渡し、 Markdown記法で -
を先頭に付与してみたいと思います。
# `seq 1 5` の実行結果(1 2 3 4 5)を1つずつ取り出し、 `echo '-' 1` のように実行していく
$ seq 1 5 | xargs -n 1 echo '-'
- 1
- 2
- 3
- 4
- 5
正しく動作しました。
ここでちょっと意地悪をしてみます。seq 6 5
と言うコマンドを実行し、 xargs
に実行結果を渡すようにしてみます。
$ seq 6 5 | xargs -n 1 echo '-'
-
なぜか - (ハイフン)が1つだけ出力されてしまいました。
受け取った標準入力が空っぽだった場合でも xargs
は echo '-'
を最低1回は実行してしまうようです。
-r
オプションを付与する
これを回避するために、 -r
オプションを付与します。
# こちらはオプション無しのときと同様
$ seq 1 5 | xargs -r -n 1 echo '-'
- 1
- 2
- 3
- 4
- 5
# 何も出力されない
$ seq 6 5 | xargs -r -n 1 echo '-'
-r
オプションですが、 ロングオプションとして --no-run-if-empty
があります。
こちらのほうがわかりやすいので利用したいところですが、MacOS標準のxargsコマンドには --no-run-if-empty
オプションがありません。
ショートオプションである -r
はどのUnix系OSでも利用できるようですので(少なくともLinux、MacOS、Brewでインストールしたxargsでは使えました。)、
こちらを利用しておくのが無難でしょう。
ひとこと
「これをデフォルト挙動にしてほしかった」と言いたいところですが、以下のようなコマンドを実行する場合にはこの挙動が望ましいのでしょう。
# カレントディレクトリ配下にはファイルが一切ないものとします
$ find . -type f | xargs ls -ls
total 0
# カレントディレクトリ配下にはファイルが一切ないものとします
$ find . -type f | xargs du -hs
0 .
ディスカッション
コメント一覧
まだ、コメントがありません