シェルスクリプト

シェルスクリプト入門

Linuxのコマンドを組み合わせて、繰り返し作業を自動化する方法を、実行結果と一緒に学びましょう。

Bash 5系を中心に、Linux・WSL・macOSなどのターミナルを対象にしています。

シェルスクリプト入門の講座一覧

Bashの導入

Linux・WSLではBashが標準で使えることが多く、macOSではターミナルを開けば始められます。bash --versionで確認し、WindowsのPowerShellではなくWSLのUbuntuを使う場合は、必要に応じてsudo apt install bashを実行してください。sudoは管理者権限で実行するため、実行時にユーザーのパスワードを求められることがあります。

01

シェルスクリプトとは

シェルは、ターミナルへ入力したコマンドを解釈して実行するプログラムです。シェルスクリプトは、そのコマンドをファイルへ保存し、変数、条件分岐、繰り返し、関数などを加えて再利用できるようにしたものです。

この講座で作れるもの
  • 指定したファイルのバックアップ
  • ログから必要な行だけを集める処理
  • 複数のファイルをまとめて整理する処理
  • 開発環境の確認や準備を自動化する処理

シェルスクリプトは短く書けますが、ファイル名の空白、入力値、権限、コマンドの失敗を意識する必要があります。この講座では、まず動く例を試し、そのあと安全に書き換える順番で進みます。

02

実行環境を確認する

Linux、WSL、macOSのターミナルなど、Bashが動く環境を使います。まず自分がどのシェルを使っているかと、Bashのバージョンを確認しましょう。

シェルを確認COMMAND
printf '現在のシェル: %s\n' "$SHELL"
bash --version | head -n 1
pwd
表示例OUTPUT
現在のシェル: /bin/bash
GNU bash, version 5.2.21(1)-release (x86_64-pc-linux-gnu)
/home/mity

バージョンやホームディレクトリは環境によって異なります。以降は、重要なファイルを置かない練習用ディレクトリを作って作業します。

練習場所を作るCOMMAND
mkdir -p ~/shellscript-practice
cd ~/shellscript-practice
pwd
実行結果の例OUTPUT
/home/mity/shellscript-practice
安全のために 練習中はホームディレクトリ直下や本番サーバーで削除コマンドを試さないでください。作業前にpwd、対象確認にlsを実行する習慣を付けます。
03

最初のスクリプトを作る

hello.shというファイルを作り、Bashへ処理を渡します。先頭のシバンは、このファイルをどのプログラムで実行するかを示します。

hello.shBASH
#!/usr/bin/env bash

printf 'こんにちは、シェルスクリプト!\n'
実行するCOMMAND
bash hello.sh
chmod u+x hello.sh
./hello.sh
実行結果OUTPUT
こんにちは、シェルスクリプト!
こんにちは、シェルスクリプト!

bash hello.shはBashへファイルを渡す方法、./hello.shは実行権限を付けたファイルを直接実行する方法です。./は現在のディレクトリを表します。

04

変数と引用符

変数へ値を入れるときは、変数名の前に$を付けません。値を取り出すときに$nameと書きます。代入の=の前後に空白は入れません。

変数を使うBASH
#!/usr/bin/env bash

name='Mity'
score=85
printf '%sさんの得点は%s点です。\n' "$name" "$score"
実行結果OUTPUT
Mityさんの得点は85点です。

文字列は基本的にダブルクォートで囲み、変数の展開を止めたい固定文字列にはシングルクォートを使います。特にパスや入力値を使うときは、空白で分割されないよう必ず引用します。

文字列とコマンド置換BASH
directory="$HOME/shellscript-practice"
today=$(date '+%Y-%m-%d')
printf '作業場所: %s\n日付: %s\n' "$directory" "$today"

バッククォートではなく$(...)を使うと、入れ子にしやすく読みやすくなります。詳しくは変数・引用・終了ステータスで練習します。

05

コマンドを組み合わせる

コマンドの標準出力は、画面へ表示するだけでなく、ファイルへ保存したり別のコマンドへ渡したりできます。

書き方役割
> file出力をファイルへ書き込み、既存内容を上書き
>> file出力をファイル末尾へ追加
command1 | command2左の出力を右の入力へ渡す
command1 && command2左が成功したときだけ右を実行
出力とパイプCOMMAND
printf 'apple\norange\ngrape\n' > fruits.txt
grep 'an' fruits.txt
cat fruits.txt | wc -l
実行結果OUTPUT
orange
3

grepは一致する行、wc -lは行数を表示します。パイプをつなぐと処理を小さく分けられますが、途中の結果を確認しながら組み立てることが大切です。

06

条件分岐

ifと[[ ... ]]を使うと、ファイルの存在や文字列、数値を確認できます。

ファイルの有無を調べるBASH
file='fruits.txt'

if [[ -f "$file" ]]; then
    printf '%s は通常ファイルです。\n' "$file"
elif [[ -d "$file" ]]; then
    printf '%s はディレクトリです。\n' "$file"
else
    printf '%s は見つかりません。\n' "$file" >&2
    exit 1
fi
実行結果の例OUTPUT
fruits.txt は通常ファイルです。

-fは通常ファイル、-dはディレクトリを意味します。>&2でエラーメッセージを標準エラーへ送り、exit 1で失敗を呼び出し元へ伝えています。

数値の比較BASH
count=$(wc -l < fruits.txt)
if (( count >= 3 )); then
    printf '3行以上あります。\n'
else
    printf '3行未満です。\n'
fi
実行結果の例OUTPUT
3行以上あります。
07

繰り返しと配列

複数のファイルや値を順番に処理するときはforを使います。回数が条件で決まる処理や、入力を一行ずつ読む処理にはwhileを使います。

forで値を処理するBASH
colors=('red' 'green' 'blue')
for color in "${colors[@]}"; do
    printf '色: %s\n' "$color"
done
実行結果OUTPUT
色: red
色: green
色: blue

"${colors[@]}"は配列の要素を一つずつ保ったまま展開します。単純な$colorsでは先頭要素だけになるため、配列全体を扱うときは書き方に注意します。

whileで行を読むBASH
while IFS= read -r line; do
    printf '読み込み: %s\n' "$line"
done < fruits.txt

IFS=とread -rを付けると、行頭の空白やバックスラッシュを意図せず変換しにくくなります。

08

ファイルとテキストを処理する

ファイル処理では、対象を確認してから作成・コピー・移動します。まずは練習用ディレクトリの中だけで試してください。

ファイルを整理するCOMMAND
mkdir -p reports/archive
printf 'done\n' > reports/today.txt
cp reports/today.txt reports/archive/today.txt
find reports -type f -name '*.txt' -print
表示例OUTPUT
reports/archive/today.txt
reports/today.txt

findの検索条件は、いきなり-deleteへつなげず、最初は-printで対象を確認します。ファイル名に空白があっても扱えるよう、パスを変数へ入れるときも展開するときも引用します。

ログを作るCOMMAND
printf 'INFO start\nERROR timeout\nINFO retry\n' > application.log
cat application.log
実行結果OUTPUT
INFO start
ERROR timeout
INFO retry
ログからエラーだけを集めるBASH
log='application.log'
if [[ ! -f "$log" ]]; then
    printf 'ログがありません: %s\n' "$log" >&2
    exit 1
fi
grep -n 'ERROR' "$log" > errors.txt || true
printf 'エラー一覧を errors.txt に保存しました。\n'
実行結果の例OUTPUT
エラー一覧を errors.txt に保存しました。

一致する行がないとgrepは終了ステータス1を返します。検索結果が空でもスクリプトを失敗にしたくない場合に|| trueを使う例ですが、エラーを隠すために常用してはいけません。

09

関数と引数

処理を関数へ分けると、同じ確認を複数の場所で再利用できます。関数内の変数にはlocalを付け、外側の変数を意図せず変更しないようにします。

usage.shBASH
show_usage() {
    printf '使い方: %s ファイル名\n' "$0"
}

if [[ $# -ne 1 ]]; then
    show_usage >&2
    exit 2
fi

target="$1"
printf '対象: %s\n' "$target"
実行コマンドCOMMAND
bash usage.sh reports
実行結果の例OUTPUT
対象: reports

$0はスクリプト名、$1は1番目の引数、$#は引数の個数です。引数が足りないときに使い方を表示して終了すると、実行方法が分かりやすくなります。

戻り値を使う関数BASH
is_readable() {
    local path="$1"
    [[ -r "$path" ]]
}

if is_readable 'fruits.txt'; then
    printf '読み込み可能です。\n'
fi
実行結果の例OUTPUT
読み込み可能です。

関数の最後に実行したコマンドの終了ステータスが、関数の戻り値になります。値を表示する関数と、成功・失敗を返す関数を使い分けます。

10

安全な書き方と次の学習

自動化する処理ほど、成功したときだけでなく失敗したときの動きを決めておく必要があります。未定義変数、パイプ途中の失敗、入力値を確認し、ログを残すようにします。

安全策を加えた入口BASH
#!/usr/bin/env bash
set -Eeuo pipefail

log() {
    printf '[%s] %s\n' "$(date '+%F %T')" "$*"
}

trap 'printf "エラー: %s行目\n" "$LINENO" >&2' ERR
log '処理を開始します。'
実行結果の例OUTPUT
[2026-10-09 10:00:00] 処理を開始します。

set -e、set -u、set -o pipefailは便利ですが、例外的に失敗を許したい処理との相性を確認する必要があります。意味を理解してから少しずつ追加しましょう。

各テーマの詳しい例は、上部の講座一覧から進めます。最後に総合練習問題で、ログ集計とバックアップを組み合わせた小さなスクリプトを作ります。