シェルスクリプトの書き方入門 - Bash変数・条件分岐・ループ
シェルスクリプトは、Linuxシステムでの作業を自動化する強力なツールです。この基礎編では、Bashスクリプトの基本構文から条件分岐、ループ処理まで、実践的な例とともに学習します。
はじめてのシェルスクリプト
基本構造
#!/bin/bash # これはコメントです echo "Hello, Shell Script!" echo "現在の日時: $(date)" echo "ユーザー名: $USER"
スクリプトの作成と実行
ステップ1: ファイル作成
$ nano hello.sh
上記のコードを入力して保存する。
ステップ2: 実行権限の付与
$ chmod +x hello.sh
ステップ3: スクリプト実行
$ ./hello.sh
Hello, Shell Script! 現在の日時: 月 1月 11 14:30:00 JST 2025 ユーザー名: user
シェバン(Shebang)について
#!/bin/bash はシェバン(shebang)と呼ばれ、このファイルを実行するインタープリターを指定する。
#!/bin/bash— Bashを使用#!/bin/sh— POSIXシェルを使用#!/usr/bin/env bash— 環境から自動検出
変数と入力
変数の基本
#!/bin/bash
# 変数の定義(=の前後にスペースを入れない)
name="Linux User"
age=25
today=$(date +%Y-%m-%d)
# 変数の使用
echo "名前: $name"
echo "年齢: ${age}歳"
echo "今日の日付: $today"計算の例
#!/bin/bash num1=10 num2=3 sum=$((num1 + num2)) diff=$((num1 - num2)) product=$((num1 * num2)) quotient=$((num1 / num2)) echo "足し算: $num1 + $num2 = $sum" echo "引き算: $num1 - $num2 = $diff" echo "掛け算: $num1 × $num2 = $product" echo "割り算: $num1 ÷ $num2 = $quotient"
特殊変数
| 変数 | 説明 | 例 |
|---|---|---|
$0 |
スクリプト名 | ./script.sh |
$1, $2, ... |
コマンドライン引数 | 第1引数、第2引数 |
$# |
引数の個数 | 3個の引数なら3 |
$@ |
すべての引数 | "arg1" "arg2" "arg3" |
$? |
直前のコマンドの終了ステータス | 成功なら0、失敗なら非0 |
$$ |
現在のプロセスID | 12345 |
$USER |
現在のユーザー名 | user |
$HOME |
ホームディレクトリ | /home/user |
$PWD |
現在のディレクトリ | /home/user/scripts |
ユーザー入力
基本的な入力
#!/bin/bash
echo "あなたの名前を入力してください:"
read name
echo "こんにちは、${name}さん!"プロンプト付き入力
#!/bin/bash read -p "年齢を入力してください: " age read -s -p "パスワードを入力してください: " password echo echo "年齢: $age" echo "パスワードは非表示で入力されました"
複数の値を一度に入力
#!/bin/bash echo "名前と年齢をスペース区切りで入力:" read name age echo "名前: $name, 年齢: $age"
条件分岐
if文
基本的なif文
#!/bin/bash
read -p "数値を入力してください: " num
if [ "$num" -gt 0 ]; then
echo "$num は正の数です"
elif [ "$num" -lt 0 ]; then
echo "$num は負の数です"
else
echo "$num はゼロです"
fiファイル存在チェック
#!/bin/bash
filename="test.txt"
if [ -f "$filename" ]; then
echo "$filename は存在します"
echo "ファイルサイズ: $(wc -c < "$filename") bytes"
else
echo "$filename は存在しません"
echo "ファイルを作成します..."
touch "$filename"
fi条件演算子
数値比較
| 演算子 | 意味 | 例 |
|---|---|---|
-eq |
等しい | [ $a -eq $b ] |
-ne |
等しくない | [ $a -ne $b ] |
-gt |
より大きい | [ $a -gt $b ] |
-ge |
以上 | [ $a -ge $b ] |
-lt |
より小さい | [ $a -lt $b ] |
-le |
以下 | [ $a -le $b ] |
文字列比較
| 演算子 | 意味 | 例 |
|---|---|---|
= |
等しい | [ "$a" = "$b" ] |
!= |
等しくない | [ "$a" != "$b" ] |
-z |
空文字列 | [ -z "$str" ] |
-n |
空でない | [ -n "$str" ] |
ファイルテスト
| 演算子 | 意味 | 例 |
|---|---|---|
-f |
通常ファイル | [ -f file.txt ] |
-d |
ディレクトリ | [ -d /home ] |
-e |
存在する | [ -e path ] |
-r |
読み取り可能 | [ -r file ] |
-w |
書き込み可能 | [ -w file ] |
-x |
実行可能 | [ -x script ] |
case文
#!/bin/bash
echo "操作を選択してください:"
echo "1) ファイル一覧表示"
echo "2) 現在時刻表示"
echo "3) システム情報表示"
echo "4) 終了"
read -p "選択 (1-4): " choice
case $choice in
1)
echo "=== ファイル一覧 ==="
ls -la
;;
2)
echo "=== 現在時刻 ==="
date
;;
3)
echo "=== システム情報 ==="
uname -a
;;
4)
echo "終了します。"
exit 0
;;
*)
echo "無効な選択です。"
;;
esacループ処理
forループ
基本的なforループ
#!/bin/bash
# 数値の範囲
for i in {1..5}
do
echo "カウント: $i"
done
echo "---"
# ファイル処理
for file in *.txt
do
echo "処理中: $file"
wc -l "$file"
done配列を使ったループ
#!/bin/bash
fruits=("apple" "banana" "orange" "grape")
echo "果物リスト:"
for fruit in "${fruits[@]}"
do
echo "- $fruit"
doneC言語風forループ
#!/bin/bash
echo "九九表の一部:"
for ((i=1; i<=5; i++))
do
for ((j=1; j<=5; j++))
do
result=$((i * j))
printf "%2d " $result
done
echo
donewhileループ
基本的なwhileループ
#!/bin/bash
count=1
while [ $count -le 5 ]
do
echo "ループ $count 回目"
count=$((count + 1))
doneファイル読み込み
#!/bin/bash
filename="data.txt"
if [ -f "$filename" ]; then
while IFS= read -r line
do
echo "読み込み: $line"
done < "$filename"
else
echo "ファイル $filename が見つかりません"
fiuntilループ
#!/bin/bash
count=1
until [ $count -gt 5 ]
do
echo "カウント: $count"
count=$((count + 1))
doneループ制御
- break — ループを抜ける
- continue — 次の反復へ
#!/bin/bash
for i in {1..10}
do
if [ $i -eq 3 ]; then
echo "3はスキップ"
continue
fi
if [ $i -eq 8 ]; then
echo "8で終了"
break
fi
echo "数値: $i"
doneよくある間違いと落とし穴
間違い1: 変数定義時のスペース
NG(エラーになる)
name = "太郎" # = の前後にスペース age= 25 # = の後にスペース city ="東京" # = の前にスペース
「command not found」エラーになる。
OK(正しい書き方)
name="太郎" # = の前後にスペースなし age=25 city="東京"
変数の代入では = の前後にスペースを入れない。
間違い2: 変数参照時の{}忘れ
NG(予期しない結果)
filename="test" echo "$filenameback.txt" # 空になる echo "$filename_backup" # 空になる
OK(正しい書き方)
filename="test"
echo "${filename}back.txt" # testback.txt
echo "${filename}_backup" # test_backup{} で変数名の範囲を明確にする。
間違い3: if文の条件式でのスペース不足
NG(構文エラー)
if [$num -gt 5]; then # [の後ろにスペースなし if [ $num -gt 5]; then # ]の前にスペースなし
OK(正しい書き方)
if [ $num -gt 5 ]; then # [ ] の内側にスペース必須 if [[ $num -gt 5 ]]; then # [[ ]] を使う場合も同様 if (( num > 5 )); then # 算術式の場合
間違い4: 文字列比較での引用符忘れ
NG(危険な例)
if [ $name = John Doe ]; then # スペースが含まれると問題 if [ $empty_var = "" ]; then # 空の場合エラー
OK(安全な書き方)
if [ "$name" = "John Doe" ]; then # 両辺を引用符で囲む if [ "$empty_var" = "" ]; then # 空でもエラーにならない if [ -z "$var" ]; then # 空文字チェックの専用オプション
間違い5: コマンド置換での古い記法
NG(非推奨)
date=`date` # バッククォート result=`cat `which ls`` # ネストでエラー
OK(現代的な記法)
date=$(date) # $() を使用 result=$(cat $(which ls)) # ネストが容易
間違い6: 算術演算での間違い
NG(計算されない)
result = $num1 + $num2 # "result" コマンドとして解釈され command not found sum="$a + $b" # 計算されない
OK(正しい計算方法)
result=$((num1 + num2)) # 算術展開 let "result = num1 + num2" # let コマンド使用
間違いを防ぐための基本ルール
記述の基本
- 変数代入時:
=の前後にスペースを入れない - 変数使用時: 常に引用符で囲む
"$var" - 複雑な変数:
{}で囲む"${var}"
条件文の基本
[ ]の使用: 内側に必ずスペースを入れる- 文字列比較: 両辺を引用符で囲む
- 数値比較:
-eq,-gt,-ltなどを使用
デバッグとトラブルシューティング
#!/bin/bash
# デバッグモードを有効にする
set -x # コマンドの実行を表示
set -e # エラー時に停止
set -u # 未定義変数でエラー
# 変数の内容を確認
echo "DEBUG: var = [$var]"
# ファイルの存在確認
if [ ! -f "$filename" ]; then
echo "ERROR: ファイル $filename が見つかりません" >&2
exit 1
fiよくあるエラーメッセージと対処法
- 「command not found」: 変数代入時の不要なスペース、実行権限の不足 →
chmod +x script.sh - 「syntax error」: if文の
[ ]内のスペース不足、引用符の対応ミス、then/fi/doneの記述忘れ - 「Permission denied」: 実行権限なし →
chmod +x script.sh