シェルプログラムで、コマンドの出力を改行を含めて変数に保存する



さて久しぶりに単純な事にはまりました。

WebサイトコンテンツをCSV管理下に置いているので、テストサイトからコミットした時に、公開サイトで画像は自動的にアップデートされてついでに最適化もされちゃったりしたらラクチンじゃん、と思ってシェルスクリプトを書いていた時の事。

手動で行うなら以下の作業を、スクリプトにまとめて指定します。

cd /path/to/htdocs/images
cvs -q update -d | egrep "^U .*png" | sed -e 's/^U //' | xargs optipng -o1 -zc7-9 -strip all;

この時、画像ファイルの種類は .png だけではなく .jpg もあるので、2回別々に「cvs -q update -d」の出力から処理対象ファイルの一覧を得るため、これを保存しておきます。

コマンド出力を変数に保存するのはこんな感じ。

CVSLOG=$(cvs -q update -d);

所が、これを echo で grep に送ろうとすると改行が潰れてしまいます。

シェル変数内の改行が出力されない

echo ${CVSLOG}

とすると、以下の出力になる。

U image1.jpg U image2.png

echo -e も変数内の改行が出力されない

「\e」を評価しくれるという「-e」オプションを付けても駄目です(そういう風に書いてある訳でないので)。

echo -e ${CVSLOG}

出力は:

U image1.jpg U image2.png

変数の指定方法が異なる

stackoverflow で見つけた解答は、

echo ${CVSLOG}

ではなく

echo "$CVSLOG"

だと。なるほど。へえ。知らなかった。

スクリプトは、

CVSLOG=$(cvs -qn update -d);
echo "$CVSLOG" | egrep "^U .*png" | sed -e 's/^U //' | xargs optipng -o1 -zc7-9 -strip all;

でOK。