最近、ちょっとしたシェルスクリプトを書いてて、改めて思ったことがあるんだよね。地味だけど、すごく大事なこと。
そう、ファイルの存在チェック。知ってる?Bashのtestコマンド、もしくは[ ]のやつ。これ、適当にやってると、後でスクリプトが変なエラー吐いて止まったりする。正直、面倒くさがらずに最初にちゃんとやっとくのが一番だなって。うん。
で、結論から言うと…
スクリプトの最初にif [ -f "$FILE" ]とかif [ -d "$DIR" ]とかを書いておくだけで、大半の「ファイルないよ!」系エラーは防げる。マジで。これがあるだけで、スクリプトの安定感が全然違うんだ。
なんていうか、料理する前に「材料、ちゃんと全部あるかな?」って確認するみたいな感じ。当たり前だけど、意外と忘れがち。
なんでそんなに大事なの?
まあ、単純な話で。例えば、ログをファイルに書き出すスクリプトがあったとして。
もしログを保存するディレクトリ(例:/var/log/myapp/)がなかったら?いきなり書き込もうとしたら、No such file or directoryって怒られてスクリプトが止まる。それは困るよね。
だから、何かアクションを起こす前に、「そもそも、それ、そこに存在する?」って確認する癖をつけるのが重要。うん。守りの一手って感じかな。
よく使うやつ、どう使い分ける?
似たようなオプションがいくつかあって、最初はちょっと戸惑うかもしれない。個人的には、この3つを覚えておけばだいたい何とかなると思ってる。
| オプション | 何を確認するか | 個人的な使いどころ |
|---|---|---|
-e FILE |
ファイルでもディレクトリでも、とにかく「何か」が存在するか | うーん、あんまり使わないかも。「とにかくそこに何かある?」ってざっくり知りたい時だけかな。良くも悪くも大雑把。 |
-d FILE |
それが「ディレクトリ」かどうか | これはよく使う。cdする前とか、ファイルを置くためのフォルダがあるか確認する時とか。必須レベル。 |
-f FILE |
それが「通常のファイル」かどうか | これも鉄板。これから読み書きする対象がちゃんとファイルであることを確認したい時。一番出番が多いかもしれないね。 |
公式のドキュメント、man testを引けば全部書いてあるんだけど…正直、情報量が多すぎて読むの大変じゃない?笑
だから、まずはこの3つ。特に-dと-fを使いこなせるようになるのが近道だと思う。実際、日本のQiitaとか技術ブログでよく見るのも、この2つを使った実践的なパターンが多い気がするしね。結局、みんなが使うのって限られてくるんだよな。
実際のコードで見てみようか
理屈だけだとピンとこないから、いくつか簡単な例を見てみるのが早い。
まず基本、ディレクトリがあるかチェック (-d)
これは、さっきも言ったけど、何かを保存したり、移動したりする前に絶対やるべきやつ。
#!/bin/bash
# check_dir.sh
# 確認したいディレクトリ
TARGET_DIR="/home/user/logs"
if [ -d "$TARGET_DIR" ]; then
# ディレクトリがあった場合の処理
echo "✔ $TARGET_DIR は存在します。処理を続行します。"
# cd "$TARGET_DIR" とか ls -l とか…
else
# なかった場合の処理
echo "❌ $TARGET_DIR が見つかりません。作成しますか? (y/n)"
# mkdir -p "$TARGET_DIR" とか…
fi
これを実行すると、もし/home/user/logsがなければ、ちゃんと「見つかりません」って言ってくれる。いきなりエラーで落ちるより、ずっと親切だよね。個人的には、else側でディレクトリを自動で作っちゃう(mkdir -p)処理を入れることが多いかな。
次に、ファイルがあるかチェック (-f)
設定ファイルを読み込む、とか、データファイルを処理する、とか。そういう時に使う。
ここでのポイントは、-eじゃなくて-fを使うこと。だって、もし同じ名前の「ディレクトリ」があったら?ファイルを読み込もうとしてエラーになる。だから、「ファイルであること」をちゃんと確認するのが大事。
#!/bin/bash
# check_file.sh
CONFIG_FILE="$HOME/.my_app_config"
echo "設定ファイルを確認します: $CONFIG_FILE"
if [ -f "$CONFIG_FILE" ]; then
echo "✔ 設定ファイルを読み込みます。"
# source "$CONFIG_FILE" とか…
else
echo "❌ 設定ファイルが見つかりません。"
echo "デフォルト設定で動作します。"
fi
こうしておけば、設定ファイルがなくても、スクリプトは止まらずに「デフォルト設定で動く」っていう代替ルートに進める。こういうのが、安定したスクリプトってことなんだと思う。
じゃあ「-e」はいつ使うの?
正直、僕はあまり使わないんだけど…。あえて言うなら、ファイルかディレクトリか、どっちでもよくて、とにかく「同名の何か」が存在してほしくない時、とかかな。
例えば、新しいファイルかディレクトリを作ろうとしてて、既に何かがあったら上書きしちゃうかもしれないから、先に確認する、みたいな。
#!/bin/bash
# check_exists.sh
TARGET_NAME="new_project"
# -e でファイルかディレクトリか問わず存在をチェック
if [ -e "$TARGET_NAME" ]; then
echo "❌ '$TARGET_NAME' という名前のファイルかディレクトリが既に存在します。"
echo "処理を中断します。"
exit 1
else
echo "✔ '$TARGET_NAME' は利用可能です。作成処理を開始します。"
# mkdir "$TARGET_NAME" とか…
fi
こんな感じ。何かを「作る」前の安全確認だね。でも、結局-dとか-fで個別に確認する方が、後々の処理が書きやすいことが多い気はする。うん。
よくある間違いとか、気をつけること
最後に、ちょっとだけ細かい話を。これ、僕も昔よくやったミスなんだけど。
変数を使う時は、必ずダブルクォートで囲むこと。if [ -f $FILE ]じゃなくて、if [ -f "$FILE" ]みたいに。
なんでかって言うと、もしファイル名にスペース(空白)が含まれてたら、クォートがないとそこでコマンドが壊れちゃうから。例えば$FILEの中身が "My Documents" だったら、[ -f My Documents ]って解釈されて、エラーになる。
これはもう、おまじないだと思って、常に変数には""をつける癖をつけとくといいよ。うん、絶対。
まあ、そんな感じかな。すごく地味な話だったけど、こういう基礎がしっかりしてると、後々作るものが全然違ってくるから。うん、たぶん。
…で、あなたの場合はどう?シェルスクリプト書く時、どのチェックを一番よく使う?やっぱり -f かな。それとももっとマニアックなやつ?もしよかったら聞かせて。
