xargs内でのコマンドについて
xargsを使った際に想像と違う挙動を示したのでメモしておく
環境
Ubuntu-20.04
BASH_VERSION-5.0.17
現象
echoでユニコード文字列を変換させて表示させようと思った際、echoをかますとうまくいかない
$ echo -e '\uFF10' 0 $ echo -e 'FF10' | xargs -I@ echo -e '\u@' \uFF10
解決策
1回シェルを明示的に呼んであげる
$ echo 'FF10' | xargs -I@ bash -c 'echo -e "\u@"' 0
なお、これはbash3環境のmacではうまくいきませんでした。
原因
- xargsが実行するコマンドを探す際、外部コマンドのみを検索対象としているから
- そしてechoに関しては、ビルドインコマンドと外部コマンドでの挙動が異なる
# xargsの挙動 ## 外部コマンドの存在するwhichの場合 $ type -a which which is /usr/bin/which which is /bin/which $ echo 'ls' | xargs -I@ which ls /usr/bin/which # whichは発動している ## 外部コマンドが存在しないtypeの場合 $ type -a type type is a shell builtin # ビルドインコマンドしか存在しない $ echo 'ls' | xargs -I@ type ls xargs: type: No such file or directory # echoの挙動 $ type echo echo is a shell builtin $ type -a echo echo is a shell builtin echo is /usr/bin/echo echo is /bin/echo ## ビルドインコマンド(通常) $ echo -e '\uFF10' 0 ## 外部コマンド $ /usr/bin/echo -e '\uFF10' \uFF10
補足
whichとtype
- whichとtypeは挙動が似ているが、この違いもビルドインコマンドか外部コマンドかで説明できる
- typeの方がビルドインコマンドである分、より正確に実行されるコマンドを把握している
$ type echo echo is a shell builtin $ which echo /usr/bin/echo
解決策2
- そもそも、xargs中では外部コマンドである
printf
を使う
$ echo '\uFF10' | xargs -I@ printf '\u@' 0