理系学生日記

おまえはいつまで学生気分なのか

パイプ前のコマンドの結果が空だったら xargs は何もしないようにする

みなさん xargs を使うときって良くあると思うんですけど、ご存知の通り通常 xargs はパイプの後段に配置します。

たとえば、doc ディレクトリ配下のファイルを lint したいとして、以下のようにする場合があります。

$ find doc -type f -print0 | xargs -0 textlint --preset preset-japanese

しかし、もしこの前段の find コマンドが何も標準出力に出力しない場合、textlint は必須の引数がないとして失敗してしまいます。

$ find tmp -type f -name \*.hoge -print0 | xargs -0 textlint --preset preset-japanese
textlint [options] file.md [file|dir|glob*]

Options:
  -h, --help                 Show help.
  -c, --config path::String  Use configuration from this file or sharable config.
(snip)

これを防ごうと思うと、

  • 前段の find コマンドの標準出力があるかないかを wc あたりで確認して、
  • あれば後段の xargs を呼び出す

というようなカッコわるいことをしないといけないのかなと思っていたら、xargs にそのものズバリなオプション --no-run-if-empty がありました。 以下は man gxargs からの引用です。

-r, --no-run-if-empty
   If  the standard input does not contain any nonblanks, do not run the command.  Normally, the command is run once even if there
   is no input.  This option is a GNU extension.

(xargs にとっての)標準入力に何もなければ、コマンドそのものを実行しないという、まさにそのものズバリ。 これを使うことによって、何も find にヒットしなくてもエラーがなくなりました。知らんかったわ。

$ find tmp -type f -name \*.hoge -print0 | xargs -0 --no-run-if-empty textlint --preset preset-japanese
$

なお、ディレクトリ配下のファイルに textlint をかける場合、textlint の引数にディレクトリ名を与えるだけで良いです。