Linux講座にようこそ。このページは「Linuxの使い方 - 第6章 シェルスクリプトの作り方」です。

Linuxの使い方

6. シェルスクリプトの作り方(1/8)

6.1 概要

UNIX系OSでは実行したいコマンドをファイルに記述しておき、コマンド名として、そのファイルを指定することにより、ファイル中のコマンドを実行することが出来ます。このコマンドを記述したファイルをシェルスクリプトと呼んでいます。シェルスクリプトに記述するコマンドの形式は、ターミナル・エミュレータ上で実行するときとまったく同じですし、ファイルは普通のテキストファイルです。また、コンパイルのような前処理も必要ありません。

ここでは、次の内容について説明します。

例題のシェルスクリプトの実行環境
【図6-1】例題のシェルスクリプトの実行環境
コマンドサーチパスの設定をしているため、コマンド名としてファイル名を指定すれば実行できます

以降の説明での例題の実行環境は図6-1のようになっています。ホームディレクトリの下にmybinディレクトリがあり、そこにシェルスクリプトが置いてあります。そして、環境変数PATHにmybinを登録してあります。(コマンドサーチパスの設定)

シェススクリプトの名称には拡張子の".sh"が付けてありますが、シェルスクリプトであることを明確にするために付けているだけです。それ以上の意味はありません。

6.2 実行方法とよく使うコマンド

6.2.1 作成方法と実行方法

シェルスクリプトはテキストファイルですので、viなどのテキストエディタで作成します。シェルスクリプトに記述するコマンドについては特別な制限はありませんので、ターミナル・エミュレータ上で実行する場合と同じ形式でコマンドを記述します。ただし、1つだけ特別なこととして、シェルスクリプト中のコマンドを処理するシェルのパス名を先頭に指定します。これを省略するとログインシェル(ターミナル・エミュレータを開いた時に起動しているシェル)で処理されます。Linuxディストリビューションの場合、Bashが標準になっていると思いますので省略しても動くと思いますが、確実を帰すために指定しておいたほうが良いでしょう。

#!/bin/bash ← bash用のシェルスクリプトの指定です
(コマンド群)

シェルスクリプト中に注釈(コメント)を記述することが出来ます。#(番号記号)を行の先頭に記述すれば行全体が、行の途中に記述すれば#以降がコメントになります。なお、これはシェルスクリプトに特有なことではなく、ターミナル・エミュレータ上で実行するコマンドも同じです。

$ # これはコメント行です
$
$ ls # カレントディレクトリ以下のファイルやディレクトリを表示します
BACKUP    MYHOMEPAGE   SAMPLE  UTF-8  public_html
BUSINESS  MyDocuments  TMP     mybin  デスクトップ
$

シェルスクリプトを通常のコマンドと同じように実行するには、ファイルの保護モードに実行許可を与えます。通常は3種類のユーザに実行許可を与えてよいと思いますが、機密保護上問題がある場合は「所有者」だけに許可を与えるというような運用も出来ます。また、環境変数PATHにコマンドサーチパスの設定をしておけば、ファイル名の指定だけで実行できます。PATHに設定していない場合はパス名で指定します。環境変数の設定については「環境の自動設定」をご覧ください。

$ chmod ugo+x ファイルパス名 ← 全てのユーザに実行許可を与えます
$ ファイルパス名 ← 実行します

bashコマンドの引数にファイルパス名を指定して実行することも出来ますが、この場合はファイルの実行許可は不要です。また、-xオプションを指定すると、実行するコマンドを表示してから実行しますので、デバックの時にとても便利です。

$ bash ファイルパス名 ← 実行許可は不要です
$ bash -x ファイルパス名 ← 実行するコマンドを表示します

6.2.2 便利なコマンド

コマンドやコマンドの形式には、シェルスクリプトで使った場合に便利なものがいくつかあります。もちろん、それらはターミナル・エミュレータ上で入力しても使えますが、その場合はあまり有効ではないということです。ここでは、echoとreadコマンドを紹介しますが、readコマンドに必要な変数については後で説明します。

echoコマンドは引数に指定したメッセージを標準出力に出力し、readコマンドは引数に指定した変数に標準入力から入力します。readコマンドは複数の変数を指定すると、その数分のデータを入力出来ますが、個々の入力データは空白文字(スペース、タブ、改行等)で区切ります。

形式

$ echo -en メッセージ1 メッセージ2 …
$ read -p プロンプト 変数1 変数2 …
【表6-1】echoコマンド・オプション
オプション意味
メッセージ標準出力に出力するメッセージを指定します。最後のメッセージの後ろで改行します。メッセージに空白文字などを含む場合は'(アポストロフィ)または、"(引用符)で括ります。
-n改行を抑止します。当オプションを省略すると改行します。
-e表6-2のエスケープシーケンスを有効にします。これらのエスケープシーケンスは'(アポストロフィ)または、"(引用符)で括ります。
【表6-2】echoコマンドのエスケープシーケンス
エスケープシーケンス意味
\a警告音を発します。
\c改行を抑止します。
\n改行します。(複数のメッセージを指定して、それぞれのメッセージ毎に改行するような場合に使用します)
\t水平タブを出力します。

readコマンドは変数を複数指定出来ますが、入力データの数より変数の数のほうが多い場合は、残りの変数の値は空(ヌル)になります。また、入力データのほうが多い場合は、最後の変数に残りのデータ全てが格納されます。

【表6-3】readコマンド・オプション
オプション意味
-p プロンプト指定したプロンプト(入力促進文字列)を標準エラー出力に出力します。当オプションは省略可能です。プロンプトに空白文字などを含む場合は'(アポストロフィ)または、"(引用符)で括ります。
変数入力したデータを格納する変数です。

6.2.3 例題

例題1

echoとreadコマンドをターミナル・エミュレータ上で実行して動作を確認します。

$ echo ← 引数を指定しません
 ← 改行のみ行います
$ echo Hello World ← 「Hello」が第1引数、「World」が第2引数です
Hello World
$ echo Hello     World
Hello World ← 第1引数と第2引数の間に半角スペースが複数あっても無視されます
$ echo 'Hello     World' ← アポストロフィで括っているので「Hello     World」が第1引数です
Hello     World
$ echo -e 'Hello World!!\c'
Hello World!!$  ← 改行を抑止したのでメッセージの最後にシェルのプロンプト($)が表示されます
$ echo -e 'No.\nName\nE-Mail'
No. ← \nによる改行です
Name ← \nによる改行です
E-Mail ← メッセージの最後は自動的に改行されます
$ echo -e 'No.\tName\tE-Mail'
No.     Name    E-Mail ← /tにより等幅(半角8文字分)で表示されます
$
$ read -p Input pleas ans
Input ← 「Input」が第2引数のプロンプトで、pleasとansは入力データを格納するための変数です。
         入力待ちになりますので入力します。最後はEnterキーです
$ read -p 'Input pleas' ans
Input pleas ← アポストロフィで括っているので「Input pleas」が第2引数のプロンプトです。入力待ちになります
$

readコマンドでデータを入力して結果を確認します。(変数に格納されている値はecho $変数名で表示できます)

$ read -p 'Input pleas : ' data1 ← 入力したデータを格納する変数(data1)を1つ指定します
Input pleas : hello ← 文字列「hello」を1つ入力します
$ echo $data1 ← 入力したデータを確認します
hello
$ 
$ read -p 'Input pleas : ' data1 data2 ← 入力したデータを格納する変数を2つ指定します
Input pleas : hello world ← 文字列を2つ入力します(文字列を空白文字で区切ります)
$ echo $data1
hello
$ echo $data2
world
$ 
$ read -p 'Input pleas : ' data1 ← 入力したデータを格納する変数を1つ指定します
Input pleas : hello world ← 文字列を2つ入力します
$ echo $data1
hello world ← 入力した文字列が全てdata1に格納されます
$ 
$ read -p 'Input pleas : ' data1 data2 data3 ← 入力したデータを格納する変数を3つ指定します
Input pleas : hello world ← 文字列を2つ入力します
$ echo $data1
hello
$ echo $data2
world
$ echo $data3
$ ← 余分な変数(data3)は空です
$

例題2

ホームディレクトリの下のmybinディレクトリのバックアップを取ります。2~3行目はコメント(注釈)行です。(ex01.sh)

#!/bin/bash
# 機能  :  ~/mybinの下のバックアップを~/BACKUPに取ります
# 作成  :  メリー
 
cd ~/mybin                                   # カレントをmybinに移動
tar -cjvf ~/BACKUP/backup.tar.bz2 .           # バックアップ取得
 
echo "バックアップ完了"
$ ex01.sh
bash: /home/merry/mybin/ex01.sh: Permission denied ← 実行許可を与えていないので実行できません
$ chmod ugo+x ./mybin/ex01.sh ← 実行許可を与えます
$ ls -l ./mybin/ex01.sh
-rwx--x--x 1 merry merry 292 11月 29 09:02 ./mybin/ex01.sh
$
$ ex01.sh
./ ← 以降はtarコマンドの実行結果です
./hello.c
./hello.prg
./ex01.sh
バックアップ完了 ← echoコマンドの実行結果です
$

例題3

バックアップ実行前に確認メッセージを出力します。(ex02.sh)

#!/bin/bash
# 機能  :  ~/mybinの下のバックアップを~/BACKUPに取ります
# 作成  :  メリー
 
read -p "バックアップを開始します" ans            # ansは変数
 
cd ~/mybin                                       # カレントをmybinに移動
tar -cjvf ~/BACKUP/backup.tar.bz2 .               # バックアップ取得
 
echo "バックアップ完了"
$ ex02.sh
バックアップを開始します ← readコマンドのプロンプトです。Enterで実行を開始します
./
./hello.c
./hello.prg
./ex02.sh
./ex01.sh
バックアップ完了
$

例題4

完了メッセージに実行日時を含めます。(「YYYY年MM月DD日 HH時MM分SS秒 : バックアップ完了」のメッセージを出力します)(ex03.sh)

#!/bin/bash
# 機能  :  ~/mybinの下のバックアップを~/BACKUPに取ります
# 作成  :  メリー
 
cd ~/mybin                                      # カレントをmybinに移動
tar -cjvf ~/BACKUP/backup.tar.bz2 .              # バックアップ取得
 
echo "$(date '+%c') : バックアップ完了"         # 日時とメッセージを出力
$ ex03.sh
./
./hello.c
./hello.prg
./ex02.sh
./ex03.sh
./ex01.sh
2017年11月29日 09時28分45秒 : バックアップ完了
$