xargsの違い

GNUとBSDの挙動の違いメモ

パイプ等と合わせて入力を引数としてコマンド実行するxargsですが、GNU/BSDで違いが大きいようです。

入力がからの時に実行するか

$ echo world! | xargs echo hello  # echo hello world! と等価

ではパイプによる入力がからの時どうなるのか
BSD系では

$ echo | xargs echo hello
$ echo $?
0

何も表示されず、ステータスコードも正常です。
一方のGNU系は

$ echo | xargs echo hello
hello
$ echo $?
0

パイプ以下のechoは実行されました。

ここで例えばディレクトリにある特定ファイルを確認したい時、

$ find ./ -maxdepth 2 -name "*hogehoge*" | xargs basename

こんなことをするとして、

BSD系では、

$ find ./ -maxdepth 2 -name "*hogehoge*" | xargs basename
$ echo $?
0

何も見つからない時、何も表示せず、正常終了します。

GNU系では、

$ find ./ -maxdepth 2 -name "*hogehoge*" | xargs basename
basename: missing operand
Try `basename --help' for more information.
$ echo $?
123

引数なしでbasenameは一回実行されてエラーを起こします。

--no-run-if-empty, -r オプション

GNU系には上記のオプションがあり、BSD系に挙動を合わせることができます。一部のBSD系は-rオプションを擬似オプション(何も動作しないオプション)として導入しています。

social