はらへり日記

腹に弾丸

CentOS7とOS X Mavericksのechoコマンドの違いについて

8/9(日) @bataさんにご指摘いただいて追記しました!

研修でこれから書く予定のWebアプリの開発環境がCentOS7なのでそれに合わせてしこしこdotfilesを書いて、つい先日完成させた。

GitHub: sota1235/dotfiles

それを手元のMacで動かしたところ、インストールコマンドのechoの挙動がおかしかったので直した(今は直ってます)。

直す前

インストールにそれっぽさを出すため、何をしてるかを色付きで出力していた(本当に簡易だが…)

一色だと寂しいし複数色にできるようにしてそれっぽさ醸し出そうと思って手元で./install叩いたらこうなった。

色がつかず、色をつけるためのエスケープシーケンスどころかecho-eオプションまで出力されてしまっている。コマッタ。

修正方法

とりあえずいろいろ調査してみる。

Shellでecho -eを叩くとどうなるか

そもそも-eオプションはエスケープシーケンスを出力しないためのもの。

適当に叩いてみるとこうなる。

うん、大丈夫。

絶対パスecho -eを叩く

なぜか/bin/echo -eすると以下のような結果になり、Shellscriptの時と同じ現象に陥る。

エー…

試しに以下のようなShellファイルを作って試す。

which echo
echo -e "hello"

んで以下の様に実行するとこうなる。

あれ、built-in commandじゃなくなってる。

ここで気づく。Shellscriptを実行してるのはshだけど今の僕のShellはzsh

てことでzshで同じファイルを実行してみる。

動いたーーーー

試しにbashでも実行してみる。

え、sh/bin/echoを実行してたのにbashだと動いてる…意味不明…

結果

表でまとめてみるとこんな感じになってる。

実行シェル which echo -eオプションは有効か
sh /bin/echo 無効
bash /bin/echo 有効
zsh shell built-in command 有効

zshはビルトインコマンドだから動くとして、shbashで挙動が違うのがマジで謎だ…困った。

結局どうしたか

結論としてはechoの替わりにprintfを使うことにしました。

ggってみるといくらかの人たちが同じようなことで困っていました。

この状態でecho-eオプション使うと実態わからないまま環境ごとに切り分けなきゃいけなくなって気持ち悪いけど、printfを使えばどの環境でもおおよそ同じ動きをするのでこちらを採用しました(色つけるのにオプションも必要ないしね)。

てことで

Before

echo -e "\e[34m$*\e[m"

After

printf "\033[34m$*\033[0m\n"

って感じになりました。

めでたしめでたし。

まとめ

  • OS Xでのecho-eオプションの挙動がアクロバティック
  • -eオプションを使う理由が色付き出力であればprintfを活用すべし

echo周りの謎は答えがわかったらまた記事書きます!もしくは誰か調べてく(ry

追記

@bataさんより以下のようなご指摘をいただきました。

そもそもwhichコマンドで検証した時点でミスしていたようです。

無知がゆえにstraceコマンドの結果をすぐに記事にできるほど理解できないので取り急ぎ(また追記します( ꒪⌓꒪))