Help us understand the problem. What is going on with this article?

Bashでif~then~else~fi文使う場合に忘れちゃならないこと

More than 5 years have passed since last update.

「ファイルの中身があったら放置。空なら消したい」時

というシェルスクリプトを書きたい場合どうするか?
素直に考えるとこんなコードを書こうとは思わないだろうか。

ファイル演算子"-s"を使うと便利よね
if [ -s /tmp/hoge.txt ]; then
  # 1バイトでも中身があれば何もしない
else
  # 0バイトだったら消す
  rm /tmp/hoge.txt
fi

Bourneシェルやzshを使っている場合はこれで大丈夫。ところが Bashで動かそうとするとエラー になってしまう。
Bashでは、thenelifelse節の後に有効なコードを置かずに済ませることは許されないらしい。上記の例のようにコメントを置いてもダメだ。

じゃあどうする?

有効なコードがありさえすればいいので、無害なコードを置けばいい。無害かつ一番軽いコードといったらnullコマンド:ではないかと思う。したがって、こう書けばよい。

nullコマンド(3行目)を置けばBashでも安全に動く
if [ -s /tmp/hoge.txt ]; then
  # 1バイトでも中身があれば何もしない
  :
else
  # 0バイトだったら消す
  rm /tmp/hoge.txt
fi

ん、nullコマンドを使ったら戻り値が保存されないって?

大丈夫、[ … ] を通る時点でそもそも保存されないので気にしなくてOK。

いや、そもそも条件を反転すれば……

そうね、[ ! -s /tmp/hoge.txt ]とすればelse節要らないよね。

でも、次の場合なんかはnullコマンド使う方が簡単よね。

世の中いつも型通りにいくとは限らない
size=$(wc -c /tmp/hoge.txt | awk '{print $1}')
if [ $size -eq 0 ]; then
  # ファイルサイズ0なら、ゴミなので安心して削除
  rm /tmp/hoge.txt
elif [ $size -eq 100 ]; then
  # ファイルサイズ100バイトなら、正常なのでここでは何もせず次へ進む。
  :
else
  # ファイルサイズがこれ以外なら、おかしいのでエラー終了
  echo 'Invalid file!' 1>&2
  exit 1
fi

というわけで覚えておきたいマメ知識だと思う。

まとめTipsも追記&バージョンアップ

どの環境でも使えるシェルスクリプトを書くためのメモというまとめTipsにもこの話を追記して、バージョン1.4にしておいたので見てねー。

richmikan@github
困った時はすぐQiitaを始めとしたTipsを表面的に鵜呑みにし、使えそうなプロダクトを拾ってきてマニュアル通りに対応するプロダクト至上主義者達よ。そんなことでは、想定外の事態に見舞われた時すぐ死ぬぞ。想定外とは、マニュアルには載ってないから想定外なのだ。マニュアル通りにしか動けぬ者は、典型的なコンビニ店員の如く薄給に喘ぐだけ。頭を使え!UNIX哲学に目覚めよ!そしてPOSIX原理主義を崇拝せよ!
https://github.com/ShellShoccar-jpn
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away