◆ if の [] にスペース必要とか 1 行で then 書くときは ; が必要とか
◆ [] の中身もプログラミング言語の if とは似てるようで全然違う

shell script ってシンプルそうでよくわからない構文で 特に自分の中では windows の bat ファイルと変に混ざってカオスな印象です
ちょっとでも複雑なことするなら php や phthon スクリプトを書いて shell script ではそれを実行するだけ にしていました

でも ときどき 5 行もいかないような簡単な処理だけってときもあります
そんなのだと shell script 直接書いてもいいかな って思いますよね


ということでやってみたら たった数行なのに 30 分くらい悩むことに

if

基本の制御構文の if ですが shell script は色々書き方があって私は基本コピペでしか使えません
それを自分で書いてみた結果が

「fi」 のあたりでシンタックスエラー と言われて原因がわからない

何がおかしいのかもわからない
参考にしてるのと何が違うんだろう……

という状態でした

結局のところの原因は

  • [] の中は空白が必要
  • then を 1 行で書くときは ; が必要

というものでした

[] の中はスペースいれる

if [ $value = "abc" ]
then
echo 1
fi

これが正しい書き方です
大抵のプログラミング言語では 文字列の中とかでなければ半角スペースは好きに入れていいもので無視するのですが shell script だとスペース入れないとダメとか入れたらダメとかがあります

if [$value = "abc"]

こうなってると $value が展開されて $value が abc なら 「[abc」 というコマンドを実行しようとしてエラーになります
開始はスペースあって閉じカッコがくっついてると 「]」 があるのに 「]」 が無いとエラーがでて何言ってるの?ということになります

1 行の then の前には ;

ネットで使い方のサンプルを探してると then が if のあとにあったり次の行にあったりしたのでコピペしてきて 2 行だったのを 1 行にしました
こういう状態です
if [ $value = "abc" ] then
echo 1
fi

fi のあたりに構文エラーと言われるのですが その辺におかしな部分もなくて意味不明です
本当の問題は then の前に 「;」 がないことです

shell script では if と then がそれぞれ文となっていて 個別の行に書かないといけないようです
それを 1 行で書くためには複数の文を 1 行で書くための 「;」 区切りとなります

if の条件

if の条件のところに書く文字列も扱いづらいです

一致のチェックは == じゃなくて = ですし 大なり記号で比較はできません
if [ $value > 0 ]; then

って書いていて なぜか 0 ってファイル名のフォルダが作られるんだけどよくわからない と困っていました
原因を探していくと この if のところで作られていて もしかしてリダイレクトされてる!? と気づけました

他にも $value のところが "$value" になっていたり書き方が人によって違ってよくわからないことが多すぎます
たぶん "" で囲んでるのは文字列に変数展開していて 変数一つだけだと無意味だと思います

ファイルが空かの確認

そもそもの今回の shell script でやりたかったことは ファイルが空かどうかを調べるだけです
空かどうかってどう判断しよう? と思ったときに思いついたのが 行数調べるコマンドがあったっけということでこうなりました

lines=`cat $file | wc -l`
if [ $lines -gt 0 ]; then
echo not-empty
fi

使ってみると動いてる……ようで動かない時があります
改行がないファイルが空扱いされます

調べてみたら wc -l は改行数を数えるコマンドであって 行数を数えるコマンドじゃないようです
Linux だと基本テキストファイルは改行文字で終わるので実質行数になるようです

Linux 上のエディタで保存すれば普通は最後に改行文字がなければ追加されます
ですが Windows から持ってきたファイルなので動いてませんでした

空ファイルのチェックなら行数でチェックする必要ないのでバイト数に変更 と考えたのですがもっと簡単に空ファイルか判断する方法がありそう と思って調べたら if の機能にあるみたいでした

if [ -s $file ]; then
echo not-empty
fi

これだけです
-s のところは test コマンドの引数になるようです
[] や -s ってすごくググりにくいキーワードばっかりです


shell script は過去の良くない仕様がいっぱい詰まってるとは言われてますが本当そのとおりですね
覚えてしまえば気にならないのかもしれませんが 新しく使い始める人が苦戦しそうなところがいっぱいです

if と case の終わりが fi と esac というのも 知っていたので今回は気にならなかったですが初めて聞いたときはフザケてるのかな?と思ったくらいですよ
せめてもうちょっと人に優しい fish shell が使えたらなぁ

自分の環境なら bash は使ってませんが デフォルトの bash を使わないといけないシーンはけっこうありますからね