xargs
で引数として置き換えられる文字列は -0
でシェルエスケープされるかと思っていたら盛大に勘違いしていたので、
sh -c
との組み合わせでの動作確認のメモ.
準備
$ touch test.txt && ls
test.txt
デフォルトの状態
$ echo -e '12345\ncheck && ls' | xargs -i{} echo {}
12345
check && ls
$ echo -e '12345\ncheck && ls' | xargs -i{} sh -c 'echo {}'
12345
check
test.txt
$ echo -e '12345\ncheck && ls' | xargs -i{} sh -c 'echo "'{}'"'
12345
check && ls
$ echo -e '12345\ncheck "&& ls' | xargs -i{} sh -c 'echo "'{}'"'
xargs: ダブルクオートが一致しません。デフォルトでは -O オプションを指定しない限り xargs でクォートは特別な意味を持ちます
12345
$ echo -e '12345\ncheck \"&& ls' | xargs -i{} sh -c 'echo "'{}'"'
12345
sh: -c: 行 0: 対応する `"' を探索中に予期しないファイル終了 (EOF) です
sh: -c: 行 1: 構文エラー: 予期しないファイル終了 (EOF) です
$ echo -e '12345\ncheck \"&& ls\"' | xargs -i{} sh -c 'echo "'{}'"'
12345
check
test.txt
-0
を指定
$ echo -ne '12345\ncheck && ls' | xargs -0 -i{} echo {} "$"
12345
check && ls $
$ echo -ne '12345\ncheck && ls' | tr "\n" "\0" | xargs -0 -i{} echo {} "$"
12345 $
check && ls $
$ echo -ne '12345\ncheck && ls' | tr "\n" "\0" | xargs -0 -i{} sh -c 'echo {} "$"'
12345 $
check
ls: '$' にアクセスできません: そのようなファイルやディレクトリはありません
$ echo -ne '12345\ncheck && ls && echo' | tr "\n" "\0" | xargs -0 -i{} sh -c 'echo {} "$"'
12345 $
check
test.txt
$
$ echo -ne '12345\ncheck && ls && echo' | tr "\n" "\0" | xargs -0 -i{} sh -c 'echo '"'"{}"'"' "$"'
12345 $
check && ls && echo $
$ echo -ne "12345\ncheck' && 'ls' && 'echo" | tr "\n" "\0" | xargs -0 -i{} sh -c 'echo '"'"{}"'"' "$"'
12345 $
check
test.txt
$
ということで、入力が信頼できるソースか特殊文字等を含まない場合以外は sh -c
などは使わない方が良さそう.
License: CC0 1.0 http://creativecommons.org/publicdomain/zero/1.0/deed.ja