🇯🇵 日本語 | 🇺🇸 English | 🇪🇸 Español | 🇵🇹 Português | 🇹🇭 ไทย | 🇨🇳 中文

【保存版】Bashで覚えるべき5つのパターンとミス回避術

これまでのBash入門シリーズで、基本的なコマンドから簡単なスクリプト作成まで、黒い画面を操るための基礎体力を身につけてきました。コマンドを組み合わせることで、日々の作業が少し楽になったのを実感できているのではないでしょうか。本当にお疲れ様でした!

さて、Bash編の締めくくりとなる今回は、一歩進んで「ただ動く」スクリプトから、「安全で、読みやすく、間違いが起きにくい」プロフェッショナルなスクリプトへとレベルアップするための、特に重要な5つのパターンと、初心者が陥りがちな「落とし穴」の回避術を伝授します。

これから紹介するのは、新しい難しいコマンドではありません。これまで学んだ知識を「どう正しく使うか」という、いわば運転のコツのようなものです。車の運転を覚えたての人が、雨の日や夜道でも安全に走るためのテクニックを学ぶように、あなたも今日の記事で、どんな状況でも安心して実行できるスクリプトの書き方をマスターしましょう!


パターン1:変数は必ず「ダブルクォート」で囲むべし!

これはBashスクリプトにおける絶対の黄金律です。変数をダブルクォート " " で囲むことを怠ると、予期せぬエラーの最大の原因となります。特に、変数の中にスペース(空白)が含まれる場合に問題が顕著になります。

ありがちなミス:クォートなしの変数

例えば、ファイル名にスペースを含むディレクトリを作成しようとする、以下のスクリプトを見てみましょう。

#!/bin/bash
DIR_NAME="My Project"
mkdir $DIR_NAME

このスクリプトを実行すると、Bashは mkdir My Project というコマンドとして解釈してしまい、「My」と「Project」という2つの別々のディレクトリが作られてしまいます。これは意図した結果ではありません。


ベストプラクティス:変数を " " で囲む

この問題を解決するには、変数をダブルクォートで囲むだけです。これにより、Bashはスペースを含んだ文字列全体を「一つの塊」として正しく認識してくれます。

#!/bin/bash
DIR_NAME="My Project"
mkdir "$DIR_NAME" # 変数をダブルクォートで囲む!
echo "ディレクトリ '$DIR_NAME' を作成しました。"

この単純な習慣が、あなたのスクリプトを遥かに堅牢にします。「変数は常にダブルクォートで囲む」と心に刻みましょう。


パターン2:エラーが起きたら即座に止まる安全設計

Bashスクリプトの怖いところは、途中で何かのコマンドが失敗しても、お構いなしに後続の処理を続けてしまう点です。例えば、「ディレクトリを移動してから、その中でファイルを削除する」というスクリプトで、移動に失敗したらどうなるでしょう?意図しない場所でファイルが削除されてしまう大惨事になりかねません。

これを防ぐため、スクリプトの冒頭に以下のおまじないを書きましょう。

set -e

set -e は、スクリプト内で実行したコマンドが一つでもエラーになった場合、その時点でスクリプトの実行を直ちに中断してくれる、いわば「安全装置」です。以下のスクリプトでその効果を見てみましょう。


#!/bin/bash
set -e # 安全装置をON

echo "処理を開始します..."

# 存在しないディレクトリへ移動しようとして、ここでエラーが発生
cd /non-existent-directory

# set -e があるため、この行は決して実行されない
echo "このメッセージは表示されません。"

このスクリプトを実行すると、cdコマンドが失敗した時点で処理が止まり、最後のechoは実行されません。重要な処理を行うスクリプトには、必ずこの一行を記述するようにしましょう。


パターン3:コマンドの実行結果を変数に入れる

スクリプトを書いていると、「コマンドを実行した“結果”を、別のコマンドや変数で使いたい」という場面が頻繁にあります。例えば、バックアップファイル名に今日の日付を入れたい、などです。

これにはコマンド置換 (Command Substitution) という機能を使います。書き方は $(コマンド) です。

#!/bin/bash
set -e

# 今日の日付を YYYY-MM-DD 形式で取得し、変数に格納
TODAY=$(date "+%Y-%m-%d")

# ファイル名に日付を組み込む
BACKUP_FILENAME="backup_${TODAY}.tar.gz"

echo "バックアップファイル名: $BACKUP_FILENAME"
# tar -czf $BACKUP_FILENAME /path/to/backup/source

$(date "+%Y-%m-%d") の部分が、dateコマンドの実行結果(例: 2025-07-06)に置き換わります。これにより、動的で分かりやすいファイル名を簡単に生成できます。


パターン4:ファイルを一行ずつ安全に処理する

テキストファイル(ドメインのリスト、URLのリストなど)を読み込んで、一行ずつ何かの処理を行うのは、スクリプトの典型的な利用例です。しかし、この処理には初心者が陥りやすい「落とし穴」があります。

よくあるNGパターン

for line in $(cat file.txt) のような書き方は、ファイル内にスペースが含まれていると正しく処理できないため、避けるべきです。

安全なベストプラクティス:`while read`ループ

ファイルを一行ずつ安全かつ効率的に処理するための定型パターンが、while readループです。少し複雑に見えますが、このままの形で覚えてしまうのが一番です。

まず、処理対象のリストファイル `domains.txt` を用意します。

example.com
example.net
example.org

次に、このファイルを読み込んで処理するスクリプトです。

#!/bin/bash
set -e

INPUT_FILE="domains.txt"

while IFS= read -r line
do
  echo "Processing domain: $line"
  # ここで ping $line や curl http://$line/ などの処理を行う
done < "$INPUT_FILE"

この構文は、行の先頭や末尾にあるスペースを維持し、特殊な文字も正しく扱えるため、あらゆるテキストファイルの処理に応用できます。


パターン5:一時ファイルを安全に作成・削除する

スクリプトの処理の途中で、一時的な作業ファイルが必要になることがあります。このとき、/tmp/my_temp_fileのようにファイル名を決め打ちするのは危険です。もし他のプログラムが同じ名前のファイルを使っていたり、スクリプトが同時に複数実行されたりすると、ファイルが上書きされてしまいます。

安全に一時ファイルを作成するには、mktempコマンドを使いましょう。これは、誰とも重複しないユニークな名前の空ファイルを作成してくれます。

#!/bin/bash
set -e

# 安全な一時ファイルを作成し、その名前を変数に格納
TEMP_FILE=$(mktemp)

# スクリプトが終了する時(正常終了、エラー、中断など)に必ず一時ファイルを削除する
trap 'rm -f "$TEMP_FILE"' EXIT

echo "一時ファイルを作成しました: $TEMP_FILE"
echo "このファイルにデータを書き込みます..."
echo "some temporary data" > "$TEMP_FILE"

echo "ファイルの中身:"
cat "$TEMP_FILE"

echo "処理が完了しました。一時ファイルは自動的に削除されます。"

さらに、trapコマンドを組み合わせることで、「スクリプトがどんな理由で終了しても、最後には必ずこの一時ファイルを削除する」という後始末を予約できます。これにより、不要なゴミファイルがサーバーに残るのを防げます。


まとめ

お疲れ様でした!これにて、Bash入門シリーズは完結です。最終回である今回は、あなたのスクリプトを「おもちゃ」から「プロの道具」へと昇華させるための、重要な5つのパターンを学びました。

これらのパターンを意識するだけで、あなたの書くスクリプトは格段に信頼性を増し、将来の自分や他の人が読んでも理解しやすい、メンテナンス性の高いコードになります。ぜひ、これからのスクリプト作成に役立ててください。あなたのWeb制作ライフが、Bashという強力なツールを得て、さらに創造的で効率的なものになることを心から願っています!