"set -e"に関するメモ

シェルスクリプト

#!/bin/sh
set -e

とすると、コマンド実行時に戻り値が 0以外になれば即座に終了
するという便利な機能があります。しかし diffコマンドのように
戻り値 0は差分なし、1は差分あり、それ以外はエラーみたいな
感じで戻り値を利用されると、diffの部分で処理が終了してしまう
という問題があります。

#!/bin/sh
set -e

diff test/old.txt test/new.txt > test.patch
echo "finish"


のような場合, diff自体は成功しますが、それ以降が実行されず
"finish"と表示されないということが起きます。

解決方法

コマンドを ifや whileの条件として書くことで、この問題を回避できます。

#!/bin/sh

set -e

if diff test/old.txt test/new.txt > test.patch; then
    if [ $? -ge 2 ]; then
        echo "Failed"
        exit
    fi
fi

echo finish

または一時的に "set +e"で "set -e"を無効にする手があります。

#!/bin/sh
set -e

set +e
diff test/old.txt test/new.txt > test.patch
set -e

echo "finish"

おわりに

if文とかわざわざ書きたくないから、"set -e"をつけているので
若干本末転倒ですが、長いシェルスクリプトの場合は diffのような
コマンドが一つ含まれるということで "set -e"をはずしてしまうのも
あれなので、知っておいた方がいいことかなと思いました。

追記

はてぶの id:tmtmsさんからの指摘. ||, &&でも OKみたいです。

#!/bin/sh
set -e

diff test/old.txt test/new.txt > test.patch || true

echo "finish"