Linuxでシェルスクリプトを作成する方法【初心者向け基本ガイド】
シェルスクリプトの作成は、Linuxユーザーが必ず身につけておきたい最重要スキルのひとつです。シェルスクリプトを活用すれば、手作業で一行ずつ実行すると面倒な反復タスクを効率的に自動化できます。
このチュートリアルでは、すべてのLinuxユーザーが押さえておくべき基本的なシェルスクリプトの操作方法を、実例とともにわかりやすく解説します。
1. 簡単なシェルスクリプトを作成する
シェルスクリプトとは、ASCIIテキストで構成されたファイルのことです。まずはテキストエディタを使って、簡単なシェルスクリプトを作成してみましょう。テキストエディタにはコマンドライン型とGUI型のさまざまな種類がありますが、本ガイドではvimエディタを使用します。
実行すると「Hello world」と表示されるシンプルなスクリプトから始めます。
$ vim hello.sh
以下の内容をファイルに貼り付けて保存してください。
#!/bin/bash
# Hello worldメッセージを表示
echo "Hello World!"
それでは、このシェルスクリプトを行ごとに確認していきましょう。
- 最初の行
#!/bin/bashはシバン(shebang)と呼ばれる特別な記述で、スクリプトを解釈するためにどのプログラムを使用するかを示します。この場合、/bin/bashで示されるbashシェルが使われます。他のスクリプト言語の例としては、Pythonなら#!/usr/bin/python3、Perlなら#!/usr/bin/perlといったシバンが使用されます。 - 2行目はコメントです。コメントはスクリプトの内容を説明するための文で、実行時には処理されません。コメントは必ずハッシュ記号
#で始まります。 - 最後の行は、端末に「Hello World」メッセージを出力するコマンドです。
次に、chmodコマンドで実行権限を付与し、スクリプトを実行可能にします。
$ chmod +x hello.sh
最後に、以下のいずれかのコマンドでシェルスクリプトを実行します。
$ bash hello.sh
または
$ ./hello.sh

2. 条件分岐(if文)でコードを実行する
他のプログラミング言語と同様、bashスクリプトでも条件分岐を使って判断を行います。構文はわずかに異なる程度です。ここではif、if-else、elifの各条件文を取り上げます。
if文のみの例
if文は単一または複数の条件をテストできます。まず、if文の基本的な使い方として、単一条件のテストから見ていきましょう。if文は if ... fi ブロックで定義されます。
if command
then
statement
fi
以下のシェルスクリプトを見てみましょう。
#!/bin/bash
echo 'Enter the score'
read x
if [[ $x == 70 ]]; then
echo 'Good job!'
fi
このシェルスクリプトは、ユーザーに点数の入力を促し、その値を変数xに格納します。入力された点数が70と一致すれば、「Good job!」という出力を返します。比較演算子 == は、変数xに格納された入力値が70と等しいかどうかを判定するために使われています。

その他に使用できる主な比較演算子は以下の通りです。
-eq:等しい-ne:等しくない-lt:より小さい-le:以下-gt:より大きい-ge:以上
たとえば、以下のif文ブロックは、入力された点数が50未満の場合に「Work Harder!」と表示します。
if [[ $x -lt 50 ]]; then
echo 'Work Harder!'
fi

if-else文の例
結果が2通りある場合(こちらかあちらか)には、if-else文が便利です。
if command
then
statement1
else
statement2
fi
以下のスクリプトは、入力された点数を読み込み、70以上かどうかをチェックします。70以上なら「Great job, You passed!」というメッセージが表示され、70未満なら「You failed」が出力されます。
#!/bin/bash
echo 'Enter the score'
read x
if [[ $x -ge 70 ]]; then
echo 'Great job, You passed!'
else
echo 'You failed'
fi

if-elif-else文の例
複数の条件とそれぞれ異なる結果がある場合は、if-elif-else文を使用します。この文は次のような形式を取ります。
if condition1
then
statement1
elif condition2
then
statement2
else
statement3
fi
たとえば、入力された番号が90、60、30のいずれかに該当するかをチェックする、宝くじ用のスクリプトがあります。
#!/bin/bash
echo 'Enter the score'
read x
if [[ $x -eq 90 ]];
then
echo "You have won the First Prize"
elif [[ $x -eq 60 ]];
then
echo "You have won the Second Prize"
elif [[ $x -eq 30 ]];
then
echo "You have won the Third Prize"
else
echo "Please try again"
fi

3. AND論理を使ったif文
AND論理演算子(&&)をif文と組み合わせると、2つの条件が両方とも満たされた場合にのみタスクを実行できます。
#!/bin/bash
echo 'Please Enter your user_id'
read user_id
echo 'Please Enter your tag_no'
read tag_id
if [[ ($user_id == "tecmint" && $tag_id -eq 3990) ]];
then
echo "Login successful"
else
echo "Login failure"
fi
4. OR論理を使ったif文
OR論理(||記号で表される)を使用する場合、期待した結果を得るためには、いずれか一方の条件が満たされていれば十分です。
#!/bin/bash
echo 'Please enter a random number'
read number
if [[ ($number -eq 55 || $number -eq 80) ]];
then
echo 'Congratulations! You've won'
else
echo 'Sorry, try again'
fi

5. ループ構造を使う
bashのループを使うと、特定の結果が得られるまで一連のタスクを繰り返し実行できます。反復タスクの処理に非常に便利です。ここでは、他のプログラミング言語にも存在する代表的なループをいくつか紹介します。
whileループ
whileループは最も扱いやすいループのひとつです。構文も非常にシンプルです。
while <some test>
do
commands
done
以下のwhileループは、実行すると1から10までのすべての数字を表示します。
#!/bin/bash
# A simple while loop
counter=1
while [ $counter -le 10 ]
do
echo $counter
((counter++))
done
whileループの動作を解説します。変数counterは1で初期化されます。変数が10以下である限り、カウンターの値は条件が満たされるまで増加し続けます。echo $counterの行により、1から10までのすべての数字が出力されます。

forループ
whileループと同様に、forループもコードを反復実行するために使われます。つまり、ユーザーが定義した回数だけコードの実行を繰り返します。
構文は以下の通りです。
for var in 1 2 3 4 5 N
do
command1
command2
done
以下のforループは、1から10まで順に処理し、その値を画面に表示します。

これを実現するより良い方法は、すべての数字を入力する代わりに、二重波括弧 { } を使って範囲を定義することです。
#!/bin/bash
# forループで範囲を指定
for num in {1..10}
do
echo $num
done
6. bashの位置パラメータ
位置パラメータとは、シェルに値が渡されたときにスクリプト内で参照できる特殊な変数ですが、直接代入することはできません。位置パラメータは $0 $1 $2 $3 ……と $9 まで続きます。$9を超える場合は、${10}、${11} … のように波括弧で囲む必要があります。
スクリプト実行時、最初の位置パラメータ$0にはシェルスクリプト名が入り、$1には端末で渡された最初の引数、$2には2番目、$3には3番目というように対応します。
それでは、以下のようにtest.shというスクリプトを作成してみましょう。
#!/bin/bash
echo "The name of the script is: " $0
echo "My first name is: " $1
echo "My second name is: " $2
次に、ファーストネームとラストネームを引数として渡してスクリプトを実行します。
# bash test.sh James Kiarie

出力を見ると、最初に表示されているのはシェルスクリプト名(この場合はtest.sh)であり、その後にシェルスクリプトで定義された位置パラメータに対応して名前が出力されていることがわかります。
位置パラメータは、変数に明示的に値を代入する代わりに、入力データを柔軟にカスタマイズできる点で非常に便利です。
7. シェルコマンドの終了ステータス(終了コード)
まず簡単な質問から始めましょう。終了コード(exit code)とは何でしょうか?
シェル上でユーザーやシェルスクリプトによって実行されるすべてのコマンドには終了ステータスがあります。終了ステータスは整数値です。
終了ステータスが0の場合、コマンドはエラーなしで正常に実行されたことを意味します。1〜255の間の値は、コマンドが失敗したか、正常に実行されなかったことを示します。
コマンドの終了ステータスを確認するには、シェル変数 $? を使用します。
- 終了ステータス1:一般的なエラー、またはsudo権限なしでファイルを編集するなどの許可されない操作によるエラーを示します。
- 終了ステータス2:コマンドやシェル組み込み変数の誤った使用を示します。
- 終了ステータス127:不正なコマンドを示し、通常は「command not found」エラーが発生します。

8. スクリプト内でシェルコマンドの出力を処理する
bashスクリプトでは、コマンドの出力を変数に格納して後で利用できます。これはシェルコマンド置換とも呼ばれ、以下の方法で実現できます。
variable=$(command)
または
variable=$(/path/to/command)
または
variable=$(command argument 1 argument 2 ...)
たとえば、dateコマンドの結果をtodayという変数に格納し、シェルスクリプトを呼び出して現在の日付を表示できます。
#!/bin/bash
today=$(date)
echo "Today is $today"

もうひとつ例を挙げましょう。Linuxシステム上の有効なログインユーザーを調べたい場合、どうすればよいでしょうか?まず、すべてのユーザー(システムユーザー、プロセスユーザー、ログインユーザー)の一覧は/etc/passwdファイルに保存されています。
ファイルを表示するにはcatコマンドを使用しますが、ログインユーザーに絞り込むには、grepコマンドで/bin/bash属性を持つユーザーを検索し、さらにcut -c 1-10コマンドで名前の先頭10文字を表示します。
catコマンドの結果はlogin_users変数に格納しています。
#!/bin/bash
login_users=$(cat /etc/passwd | grep /bin/bash | cut -c 1-10)
echo 'This is the list of login users:'
echo $login_users

以上で、簡単なシェルスクリプト作成に関するチュートリアルは終了です。本記事が皆さんの学習のお役に立てば幸いです。
-
シェルスクリプトで構文チェックのデバッグモードを実行する方法
シェルスクリプトのデバッグシリーズでは、これまでにさまざまなデバッグオプションの種類と、シェルスクリプトのデバッグモードを有効にする方法を解説してきました。 シェルスクリプトを書き終えたら、実行前に必ずスクリプトの構文を実際にチェックすることをおすすめします。出力結果を見て動作が正しいかどうかを確認するよりも、事前に構文エラーを検出する方が効率的だからです。 この記事では、構文チェック(シンタックスチェック)デバッグモードの使い方について詳しく見ていきます。前回の記事で説明した各種デバッグオプションを思い出しながら、実際にスクリプトのデバッグを行ってみましょう。 冗長(Verbose)デバッグ
-
Vimで新規シェルスクリプトに自動でカスタムヘッダーを挿入するテンプレート設定方法
この記事では、Vimエディタで新しく作成するすべてのbashスクリプトに、カスタムヘッダーを自動的に挿入するための簡単な設定方法を紹介します。この設定を行うことで、vi/vimエディタで新しい .sh ファイルを開くたびに、カスタムヘッダーが自動的にファイルの先頭へ追加されるようになります。 bashスクリプト用カスタムヘッダーテンプレートファイルの作成方法 まずは、カスタムbashスクリプトヘッダーの内容を記述したテンプレートファイル sh_header.temp を作成します。ホームディレクトリ配下の ~/.vim/ ディレクトリなどに保存しておくと管理しやすいでしょう。 $ vi ~/.