xargsについて気にしなければならないことがやたら多いので覚書を作成した。
1. findで用がすむ場合
xargsの左側の大半はfindだと思われるが、
findで全部すむのならfindですました方がよい。
なおfindでもxargsのように複数の行を結合してforkを減らすことができる。
(exec command {} +等)
2. -0オプションについて
POSIXではないが-0オプションでnull文字を区切り文字として扱う。
こうすると空白文字やクォーテーション等の文字が含まれていても
分割やエスケープが行われない。
入力側がnull文字区切りに対応している必要がある。
3. 特定の文字列をデリミタ代わりにする回避策
改行がデリミタとして使えるのであればスペース,タブをエスケープすれば良い。
入力がファイルパスの場合、正規化された表現なら、
"//"は含まれないはずなので、find .// 等を入力元にすることで
デリミタである改行とファイル名である改行を判別し、
空白文字を適切にエスケープすることができる。(具体例)
4. -Iオプションかwhile IFS= read -rを使うべき場合
この場合、複数の引数を渡すのは諦める。
5. -rオプションについて
-rオプションで空行に反応しないようにできる。
POSIXではないがgnu以外では不要な対処。
ポータビリティに拘るでのあればこちらの記事を見て対処すると良い。
6. ',",\のエスケープ
xargsは上記の文字を特別扱いして空白や改行のエスケープを行うため、
不本意なエスケープが行われないように入力を変換する必要がある。
なお、実装によるエスケープの違いはこちらの記事を参照すること。
7. 入力の末尾が改行でない場合
Linuxは問題ないが、ポータビリティを意識するなら、
grep ^を挟むなどの対策を講じる。(詳細)
8. セキュリティに関する考慮
この場合、セキュリティにうるさいシステムではxargsを使うべきではない。(リスクの詳細)
findのexecdirを使えば少しはマシになるかもしれない。
9. 引数の数で挙動の異なるコマンド
grepくらいしかこの手のコマンドを知らないが、
grepはファイル数が1個の場合はファイルパスを出力しないため、
/dev/nullを渡すのがパターンになっている。
(これにより空白行の対処も可能である。)