Bashスクリプト基礎入門|変数・条件分岐・ループを完全マスター

Linux/Unix環境で自動化を実現するならBashスクリプトが最適です。変数宣言・条件分岐・ループ処理を正しく使いこなせば、日々の運用作業を数分で完了させられます。本記事では実務で即座に活用できる具体的な書き方を、実行可能なサンプルコードと共に解説します。初心者でも1日で基本構文を習得できる内容です。


目次


Bashスクリプトとは何か

Bash(Bourne-Again SHell)はLinux/Unixシステムで標準的に利用されるシェルです。Bashスクリプトはこのシェルで実行可能なコマンド群をテキストファイルにまとめたプログラムであり、以下の特徴があります。

  • 軽量性:システムリソースをほとんど消費せず、即座に実行可能
  • 柔軟性:コマンドライン操作をそのままスクリプト化できる
  • 自動化:定型業務を自動実行し、人的ミスを排除
  • 移植性:主要なUnix系OSで動作(ただし一部の機能はOS依存あり)

特にサーバー運用やDevOps業務では、Bashスクリプトがなくてはならない存在です。例えばログファイルの整形、バックアップ処理、システム監視など、あらゆる場面で活躍します。

公式ドキュメントによると、BashはPOSIX標準に準拠しており、シェルスクリプトの事実上の標準言語となっています(出典: GNU Bash Manual)。


実行環境の準備と基本設定

1. 実行環境の確認

Bashスクリプトを実行するには以下の環境が必要です。

  • Linux/Unix系OS(Ubuntu、CentOS、macOSなど)
  • Bashシェル(通常はデフォルトでインストール済み)
  • テキストエディタ(vim、nano、VS Codeなど)

現在のBashバージョンを確認するには以下のコマンドを実行します。

bash --version
# 出力例: GNU bash, version 5.1.16(1)-release (x86_64-pc-linux-gnu)

バージョンが表示されればBashは利用可能です。macOSの場合はデフォルトでBash 3.2がインストールされていますが、Homebrew経由で最新版にアップグレードできます。

2. スクリプトファイルの作成

スクリプトファイルは通常のテキストファイルで作成します。拡張子は「.sh」が一般的ですが、必須ではありません。以下の手順で作成します。

実行手順:
1. テキストエディタで新規ファイルを作成
2. 以下の内容を入力
3. ファイル名を「hello.sh」として保存
4. 実行権限を付与
5. 実行
#!/bin/bash
# これはコメントです
echo "Hello, World!"

ファイルを保存後、実行権限を付与します。

chmod +x hello.sh
# 実行
./hello.sh
# 出力: Hello, World!

注意点:

  • Shebang(#!/bin/bash)は必須です。これによりOSがBashを使用してスクリプトを実行します。
  • 実行権限(chmod +x)がなければ「Permission denied」エラーが発生します。
  • Windows環境で実行する場合はWSL(Windows Subsystem for Linux)を使用してください。

3. 実行方法の種類

Bashスクリプトには主に3つの実行方法があります。

実行方法説明使用シーン
直接実行(./script.sh)実行権限を付与し、./で実行ローカル環境での実行に最適
bashコマンドで実行(bash script.sh)実行権限がなくても実行可能一時的な実行やテストに便利
sourceコマンドで実行(source script.sh)現在のシェル環境で実行(変数が引き継がれる)環境変数の設定などに使用

変数の宣言と活用方法

Bashスクリプトにおける変数は、データを一時的に保存するための仕組みです。他言語と異なり、変数宣言時に型を指定する必要はありません。

1. 変数の基本的な使い方

変数の宣言と代入は以下のように行います。

# 変数の宣言と代入
NAME="John Doe"
AGE=30

# 変数の参照($を付ける)
echo "Name: $NAME"
echo "Age: $AGE"

注意点:

  • 変数名には大文字・小文字の区別があります(NAMEとnameは別の変数)
  • 変数名には数字・アンダースコア・アルファベットのみ使用可能
  • 変数名の先頭に数字は使用できません
  • スペースを含む値を代入する場合はダブルクォーテーションで囲む

2. 変数のスコープ

Bashの変数には2種類のスコープがあります。

スコープタイプ説明
ローカル変数関数内でのみ有効な変数local VAR="value"
グローバル変数スクリプト全体で有効な変数VAR="value"

関数内でローカル変数を宣言するには「local」キーワードを使用します。

#!/bin/bash

GLOBAL_VAR="I'm global"

function test_scope {
    local LOCAL_VAR="I'm local"
    echo "Inside function: $LOCAL_VAR"
    echo "Inside function: $GLOBAL_VAR"
}

test_scope
echo "Outside function: $GLOBAL_VAR"
# echo "Outside function: $LOCAL_VAR"  # これはエラー(LOCAL_VARは関数内でのみ有効)

3. 特殊な変数

Bashにはシステムによって自動的に設定される特殊変数が多数存在します。主なものを以下に示します。

変数名説明使用例
$0スクリプト名echo "Script name: $0"
$1, $2, …引数($1は1番目の引数)echo "First argument: $1"
$#引数の総数echo "Number of arguments: $#"
$@すべての引数(配列として扱う)for arg in "$@"; do echo "$arg"; done
$?直前のコマンドの終了ステータス(0=成功、非0=失敗)if [ $? -eq 0 ]; then echo "Success"; fi
$$現在のプロセスIDecho "Process ID: $$"

これらの特殊変数を活用することで、柔軟なスクリプトを作成できます。

4. 変数の展開と置換

Bashでは変数に対して様々な展開操作が可能です。

構文説明
${VAR}変数の値を参照echo ${NAME}
${VAR:-default}変数が未設定または空の場合にデフォルト値を使用echo ${NAME:-Guest}
${VAR:=default}変数が未設定または空の場合にデフォルト値を代入して使用echo ${NAME:=Guest}
${VAR:?error}変数が未設定または空の場合にエラーを表示echo ${NAME:?Name is required}
${VAR%pattern}末尾のパターンに一致する部分を削除echo ${FILE%.txt}
${VAR#pattern}先頭のパターンに一致する部分を削除echo ${PATH#*:}

これらの展開機能を使いこなすことで、より堅牢なスクリプトを作成できます。


条件分岐(if文・case文)の完全ガイド

条件分岐はプログラムの流れを制御する重要な機能です。Bashではif文とcase文の2種類の条件分岐が使用できます。

1. if文の基本構文

if文の基本構文は以下の通りです。

if [ 条件式 ]; then
    # 条件が真の場合の処理
elif [ 別の条件式 ]; then
    # elifの条件が真の場合の処理
else
    # いずれの条件も真でない場合の処理
fi

注意点:

  • 条件式は角括弧[]で囲む(スペースに注意)
  • thenとfiはそれぞれ改行またはセミコロンで区切る
  • 条件式の比較演算子には特定の書式がある

2. 条件式の比較演算子

Bashにおける主な比較演算子は以下の通りです。

演算子説明文字列比較例数値比較例
= または ==等しい[ "$str1" = "$str2" ]
!=等しくない[ "$str1" != "$str2" ]
-eq等しい(数値)[ $num1 -eq $num2 ]
-ne等しくない(数値)[ $num1 -ne $num2 ]
-ltより小さい(数値)[ $num1 -lt $num2 ]
-le以下(数値)[ $num1 -le $num2 ]
-gtより大きい(数値)[ $num1 -gt $num2 ]
-ge以上(数値)[ $num1 -ge $num2 ]
-z文字列が空[ -z "$str" ]
-n文字列が空でない[ -n "$str" ]
-fファイルが存在する[ -f "/path/to/file" ]
-dディレクトリが存在する[ -d "/path/to/dir" ]

3. 実践的なif文の例

以下に実務で役立つif文の例を示します。

ファイルの存在確認

#!/bin/bash

FILE="/etc/passwd"

if [ -f "$FILE" ]; then
    echo "ファイル $FILE は存在します"
    echo "ファイルサイズ: $(du -h "$FILE" | cut -f1)"
else
    echo "ファイル $FILE は存在しません"
    exit 1
fi

引数の検証

#!/bin/bash

if [ $# -eq 0 ]; then
    echo "エラー: 引数が必要です"
    echo "使用法: $0 "
    exit 1
fi

USERNAME=$1

if ! id "$USERNAME" &>/dev/null; then
    echo "エラー: ユーザー $USERNAME は存在しません"
    exit 1
fi

echo "ユーザー $USERNAME のホームディレクトリ: $(eval echo ~$USERNAME)"

数値の比較

#!/bin/bash

read -p "年齢を入力してください: " AGE

if [ "$AGE" -lt 0 ]; then
    echo "エラー: 年齢は正の数で入力してください"
elif [ "$AGE" -lt 13 ]; then
    echo "子供"
elif [ "$AGE" -lt 20 ]; then
    echo "ティーンエイジャー"
elif [ "$AGE" -lt 65 ]; then
    echo "大人"
else
    echo "シニア"
fi

4. case文の活用

case文は複数の条件分岐をシンプルに記述できる構文です。if文よりも読みやすい場合があります。

基本構文:

case 変数 in
    パターン1)
        # 処理1
        ;;
    パターン2)
        # 処理2
        ;;
    *)
        # デフォルト処理
        ;;
esac

注意点:

  • 各パターンの終わりには;;が必要
  • *)はデフォルト処理(switch文のdefaultに相当)
  • パターンにはワイルドカード(*、?、[])が使用可能

実践例:

#!/bin/bash

read -p "OSを入力してください (linux/mac/windows): " OS

case $OS in
    linux|Linux)
        echo "Linuxシステムです"
        ;;
    mac|Mac)
        echo "macOSシステムです"
        ;;
    windows|Windows)
        echo "Windowsシステムです"
        ;;
    *)
        echo "不明なOSです"
        exit 1
        ;;
esac

case文は特にコマンドライン引数の処理や、ユーザー入力のバリデーションに適しています。


ループ処理(for・while・until)の実践テクニック

ループ処理は同じ処理を繰り返し実行する際に使用します。Bashでは主に3種類のループ構文が利用できます。

1. forループ

forループはリストや範囲の要素を順に処理する際に使用します。

基本構文

for 変数 in リスト; do
    # 処理
done

リストからのループ

#!/bin/bash

# 文字列のリスト
for FRUIT in apple banana orange; do
    echo "フルーツ: $FRUIT"
done

# 配列のループ
FRUITS=("りんご" "バナナ" "オレンジ")
for FRUIT in "${FRUITS[@]}"; do
    echo "フルーツ: $FRUIT"
done

# コマンドの出力をループ
for FILE in $(ls *.txt); do
    echo "テキストファイル: $FILE"
done

範囲を使ったループ

#!/bin/bash

# 0から9までループ
for i in {0..9}; do
    echo "数字: $i"
done

# 10から1ずつ減らすループ
for i in {10..1}; do
    echo "カウントダウン: $i"
done

# C言語風のループ
for ((i=0; i<10; i++)); do
    echo "C風ループ: $i"
done

実務例:ファイル処理

#!/bin/bash

# /var/logディレクトリのすべての.logファイルを圧縮
LOG_DIR="/var/log"
for LOG_FILE in "$LOG_DIR"/*.log; do
    if [ -f "$LOG_FILE" ]; then
        echo "圧縮中: $LOG_FILE"
        gzip "$LOG_FILE"
    fi
done

2. whileループ

whileループは条件が真の間、処理を繰り返します。

基本構文

while [ 条件 ]; do
    # 処理
done

実践例:ユーザー入力待ち

#!/bin/bash

while true; do
    read -p "続行しますか? (y/n): " ANSWER
    case $ANSWER in
        [yY]|[yY][eE][sS])
            echo "続行します"
            break
            ;;
        [nN]|[nN][oO])
            echo "終了します"
            exit 0
            ;;
        *)
            echo "yまたはnで答えてください"
            ;;
    esac
done

実務例:ログ監視

#!/bin/bash

LOG_FILE="/var/log/syslog"
LAST_SIZE=$(stat -c%s "$LOG_FILE")

while true; do
    CURRENT_SIZE=$(stat -c%s "$LOG_FILE")

    if [ $CURRENT_SIZE -gt $LAST_SIZE ]; then
        echo "ログファイルが更新されました"
        tail -n 10 "$LOG_FILE"
        LAST_SIZE=$CURRENT_SIZE
    fi

    sleep 5
done

3. untilループ

untilループは条件が偽の間、処理を繰り返します。whileループの条件を反転させたものです。

基本構文

until [ 条件 ]; do
    # 処理
done

実践例:サービスの起動確認

#!/bin/bash

SERVICE="nginx"
TIMEOUT=30
INTERVAL=2

echo "サービス $SERVICE の起動を確認中..."

until systemctl is-active --quiet "$SERVICE" || [ $TIMEOUT -le 0 ]; do
    sleep $INTERVAL
    TIMEOUT=$((TIMEOUT - INTERVAL))
    echo "残り時間: $TIMEOUT秒"
done

if systemctl is-active --quiet "$SERVICE"; then
    echo "サービス $SERVICE は正常に起動しました"
else
    echo "エラー: サービス $SERVICE を起動できませんでした"
    exit 1
fi

4. ループ制御

ループ処理を制御するためのキーワードが2つあります。

キーワード説明使用例
breakループを直ちに終了するif [ $i -eq 5 ]; then break; fi
continue現在のイテレーションを終了し、次のイテレーションに進むif [ $i -eq 3 ]; then continue; fi

実践例:

#!/bin/bash

for i in {1..10}; do
    if [ $i -eq 3 ]; then
        echo "3をスキップします"
        continue
    fi

    if [ $i -eq 8 ]; then
        echo "ループを終了します"
        break
    fi

    echo "現在の値: $i"
done

5. ループ処理のベストプラクティス

  1. ループ回数を最小化する:不要なループは処理時間の無駄
  2. ループ内で重い処理を避ける:可能な限りループ外で処理する
  3. エラー処理を実装する:ループ内でエラーが発生した場合の対処方法を考える
  4. 変数名を分かりやすくする:i, jなどの単純な変数名よりも具体的な名前を使用
  5. ループの終了条件を明確にする:無限ループにならないように注意

関数の定義と呼び出し方

関数は一連の処理をまとめて再利用可能な形で定義する機能です。Bashスクリプトの保守性と再利用性を高めるために不可欠です。

1. 関数の基本構文

Bashにおける関数の定義方法は2種類あります。

方法1:function

この記事で学んだスキルをさらに深めたい方へ

Linuxの知識をさらに深めたい方はこちらの技術書がおすすめです。コマンドラインからサーバー管理まで網羅しています。

Amazonアソシエイトプログラムを利用しています。

エラー処理とデバッグ手法

Bashスクリプトにおけるエラー処理は、予期しない動作や障害が発生した際にプログラムを安全に停止させたり、リカバリ処理を実行したりするために重要です。主な手法としては、set -e(エラー発生時に即座にスクリプトを終了)やset -u(未定義変数の使用を検出)があります。これらのオプションを活用することで、スクリプトの堅牢性を高められます。また、trapコマンドを用いて、特定のシグナル(例:EXIT)発生時に実行される処理を定義することも可能です。

デバッグにおいては、set -xを使用してコマンド実行時の詳細なログ出力を行う方法が一般的です。これにより、スクリプトの各ステップを逐一確認でき、問題箇所の特定が容易になります。加えて、echo文を挿入して変数の値や処理の流れを確認する「プリントデバッグ」も有効です。特に、ループ処理や条件分岐の内部で変数の状態を確認する際に役立ちます。

エラー処理の実践例として、以下のような手順が挙げられます。まず、コマンド実行後にステータスコード($?)を確認し、エラー時の処理を分岐させます。例えば、ファイル操作の際にif [ $? -ne 0 ]でエラーを検出し、適切なメッセージを出力して終了することができます。また、||&&を活用した短絡評価を用いることで、エラー発生時の代替処理を簡潔に記述できます。

  • デバッグ時のポイント:bash -nで構文エラーの事前チェックを行うことで、スクリプト実行前に基本的なミスを排除できます。

実務で使えるベストプラクティス

Bashスクリプトを実務で活用する際には、保守性や可読性を重視した設計が重要です。スクリプトはチームで共有されることが多いため、誰が見ても理解しやすい構造を心がけましょう。例えば、変数名はその役割を明確に表すものを使用し、コメントを適切に挿入することで後続の作業者への負担を軽減できます。また、エラー処理を適切に行うことで、予期せぬトラブル発生時にもスクリプトが停止せず、ログやメッセージを通じて原因を特定しやすくなります。

実務では、スクリプトの実行環境や依存関係を明確にしておくことも大切です。例えば、特定のコマンドやツールに依存する場合は、スクリプトの冒頭でバージョンチェックを行うことで、環境の違いによるエラーを未然に防ぐことができます。さらに、スクリプトの実行結果を記録し、定期的に実行履歴を確認することで、問題の早期発見につながります。これにより、システムの安定稼働を維持しやすくなります。

セキュリティ面でも注意が必要です。スクリプト内で機密情報を扱う場合は、環境変数や専用の設定ファイルを使用し、コード内に直接埋め込まないようにしましょう。また、ファイルやディレクトリの権限設定を見直すことで、不要なアクセスを制限し、セキュリティリスクを低減できます。これらの対策を講じることで、より安全で信頼性の高いスクリプトを運用することが可能です。

  • スクリプトの冒頭に「#!/bin/bash」を記述し、実行環境を明確にする

Bashスクリプトに関するよくある質問

Bashスクリプトの実務利用において、初心者から上級者まで共通して抱く疑問や注意点について、具体的な事例を交えながら解説します。

Q1. Bashスクリプトを書く際の基本的な注意点は何ですか?

Bashスクリプトを書く際は、まずスクリプトの冒頭に「#!/bin/bash」のシバン行を記述し、実行権限を付与する必要があります。また、変数の宣言時にはスペースを入れず「VAR=value」とする点に注意してください。さらに、コマンドの実行結果を変数に代入する際は、$(command)または`command`を使用します。これらの基本ルールを守らないと、スクリプトが正常に動作しない場合があります。

Q2. 条件分岐で「if」文を使う際のポイントはありますか?

条件分岐には「if [ 条件 ]; then ... fi」構文を使用しますが、条件式の記述方法に注意が必要です。例えば、文字列比較には「==」や「!=」を、数値比較には「-eq」「-ne」を使い分けます。また、ファイルの存在確認には「-f」や「-d」を用います。条件式の前後には半角スペースが必須である点も忘れないでください。

Q3. ループ処理で「for」文と「while」文の使い分けはどうすればいいですか?

「for」文は主に決まった回数の繰り返しやリスト要素の処理に向いており、「for i in {1..10}; do ... done」のように記述します。一方、「while」文は特定の条件が真である間、処理を繰り返す際に使用し、「while [ 条件 ]; do ... done」が基本構文です。例えば、ファイルの行ごとに処理する場合は「while read」構文が便利です。

Q4. Bashスクリプトでエラーが発生した際のデバッグ方法は?

Bashスクリプトのデバッグには「set -x」を使用してコマンド実行過程を表示したり、「set -e」でエラー発生時にスクリプトを終了させる設定が有効です。また、echo文で変数値を確認する方法もあります。さらに、専用のデバッグツールとして「bashdb」や「ShellCheck」を利用することで、より効率的に問題を特定できます。

まとめ:次に学ぶべきこと

Bashスクリプトの基礎を学ぶうえで、変数の宣言や代入、条件分岐の基本構文、そしてループ処理の活用方法は欠かせない要素です。これらを組み合わせることで、繰り返し作業の自動化や柔軟な処理フローの構築が可能になります。特に、条件分岐ではコマンドの実行結果に応じた分岐が重要であり、ループでは処理対象のデータや回数を適切に制御することが求められます。

次に取り組むべきは、関数の定義やエラー処理、そしてスクリプトのデバッグ手法です。関数を活用することでコードの再利用性が高まり、エラー処理を組み込むことで予期せぬ動作への対応力が向上します。また、デバッグツールやログ出力を適切に活用することで、スクリプトの信頼性をさらに高めることができます。これらのスキルを身につけることで、より実践的なBashスクリプトを作成できるようになるでしょう。

【編集・制作ポリシー】
本記事はInfra Academy編集部が各ベンダー公式ドキュメント・エンジニア監修をもとに作成しています。インフラ・クラウド構築は環境により異なります。本番環境への適用前に必ずテストを実施してください。情報の正確性には万全を期していますが、最新情報は各公式ドキュメントをご確認ください。 編集ポリシーはこちら
ABOUT ME
たから
フリーランスIT講師/エンジニア。 ◆経験:IT講師/インフラエンジニア/PM/マネジメント/採用/運用・保守・構築・設計 ◆取得資格:CCNA/CCNP/LPIC-1/AZ-900//サーティファイC言語/情報処理技術者 ◆サイドビジネス:アパレル事業/複数のWEBメディアを運営