Diary

Diary

日々学んだことをアウトプットする場として初めてみました

xargs内でのコマンドの挙動について

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