160
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

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

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

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

ファイル演算子"-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にしておいたので見てねー。

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
Sign upLogin
160
Help us understand the problem. What are the problem?