シェルコマンド言語


シェルコマンド言語の雑な説明

このページでは、シェルコマンド言語の使い方、ひいてはシェルスクリプトを記述するための前提となる知識を、雑に紹介するところから始めます。
一応、このツイートと関連しますw

シェル

ある程度馴染みがあるであろう Linux で説明します。

Linux は Linus Torvalds さんがメインとなって開発されている中心的プログラムである Kernel(カーネル) で動きます。
Kernel というのは、たとえばファイルの扱い方だったり、ネットワーク通信の仕方だったりを制御してくれます。

指示すれば制御してくれるのですが、思った通りにはやってくれませんので Kernel そのままでは、人が扱うのに不向きです。
そこで、何らかの形で Kernel に仕事をさせるプログラムが必要になります。

それが、キーボードから 特定の文字列(コマンド) を入力して Enter を押すと Kernel にアクセスすることができる、シェルと呼ばれるプログラムです。
Linux Kernel を包み込む 貝殻(シェル) のようなイメージをすると、良いかもしれません。

つまり Linux におけるシェルとは、コマンドラインインタープリタ(指定した文字列を適宜解釈して実行するプログラム)のことです。
bourne shell とか c shell とかいった、いくつかの種類が存在しています。

このシェルには環境変数と呼ばれる変数があり、暗黙的/明示的に様々な形で利用されます。

なお、シェル自体は Linux が参考にした UNIX で実装されている CUI でもあります。
UNIX の歴史とともにあるプログラムですが、ここでは割愛します。

コマンド

コマンドは、シェル自体にビルトインされているものもありますが、基本的には単一の目的のために作られたプログラムになります。
たとえばシェルで ls というコマンドを実行すると、カレントディレクトリ配下にあるファイルが表示されますが、これは /bin/ls というファイルを実行した結果です。

ls コマンド


type というコマンドは、どのパスで実行しているか以外にハッシュされているかどうかを表示してくれます。
ハッシュされている(位置を記憶している)と、環境変数 $PATH を検索せずにコマンドが実行されることを意味しています。

which というコマンドは、パスのどこに存在するのか教えてくれます。

インタプリタ内部では $PATH に定義されたパスの順に、コマンドと同じファイル名のプログラムを探し、最初に合致したファイルを起動します。
この PATH に . が含まれている場合、カレントディレクトリのファイルも実行対象として検索されます。

コマンド用のプログラムは、目的に沿って格納するディレクトリが分けられています。
そのディレクトリは環境変数 PATH に記述され、コマンド実行時に随時*1参照されて呼び出すプログラムが決定されます。

*1 : 場所を予め覚えているコマンドがあるといった一部例外はありますが

シェルコマンド言語

ここでは、シェルコマンド言語についてあれこれ記載します。
UNIX のシェル (CUI) で使うコマンドの仕様のことです。

シェルスクリプト

日本における IT 業界では、シェルコマンド言語で書かれたスクリプトをシェルスクリプトと呼んでいます。
むしろ、シェルコマンド言語というと「コマンドは言語じゃないだろ」と言う人もいるかもしれません。

なんでこんな書き方をしてるかというと POSIX が Shell Command Language と書いているからです。

プログラム言語は、基本的に英語圏で開発されたものなので、英語をもとにしています。
言語の和訳は、つぎのように行われています。

programming language → プログラミング言語
C Language → C 言語

なら Shell Command Language は シェルコマンド言語でしょう。
シェルコマンド言語で書いたスクリプトは、シェルスクリプトで良いと思います。

POSIX

では、POSIX というのは何か。

現在の POSIX とは UNIX を名乗る OS に共通する仕様を決めたものです。

正式名称を Portable Operating System Interface for UNIX *2 と言います。
2020 年8月現在、UNIX という商標をもち POSIX という仕様を策定している The Open Group という業界団体が仕様を公開しています。

https://publications.opengroup.org/

なお、規格としては IEEE になっているので IEEE Std 1003.1-2017 という表記になっています。

UNIX と名乗る OS は、POSIX 仕様に準拠したうえで、ライセンス料を支払う必要があります。

ちなみに Linux は POSIX に準拠していますが、ライセンス料は支払っていないので UNIX ではない、という立ち位置です。
また、Linux は Linus Torvalds が商標を持っています。

最新は 2018 Edition ですね。
何年か毎に更新されるので、参考までに。

シェルコマンド言語

前置きが少し長くなりましたが、シェルコマンド言語仕様へのアクセスは次の URL になります。

https://pubs.opengroup.org/onlinepubs/9699919799/
main
3ペインの左上から Shell & Utilities をクリックします。
すると左下ペインに、対応するメニューが表示されます。
Shell and Utilities
メニュー内容
1. Introductionどんなコマンドとユーティリティを提供するのか、その前置き
2. Shell Command Languageシェルコマンド言語の定義
3. Batch Environment Servicesバッチジョブへ提供する機能の定義
4. UtilitiesUNIX が提供する機能やコマンドの説明

*2 : なお for UNIX の部分は後付けと聞いています。

シェルスクリプト

シェルスクリプトは、シェルコマンド言語で書かれたスクリプトファイルです。

シェルスクリプトというと長いので、省略してシェルと呼ばれることもあります。
文脈で判断してください。

シェルスクリプトの書き方

シェルスクリプトはテキストなので、テキストエディタで記述します。
ファイルの形式
基本的には、コマンドを書いてファイルに保存し、bash に引数として読み込ませれば実行されます。

ファイル単体で実行するためには、最低限、以下の書き方をする必要があります。
shebang
ファイルの1行目に、つぎの文字列を書きます。
#!/bin/bash
これを shebang (シバン等と読む)と言い、UNIX の処理系ではインタープリタ(実行プログラム)を指定するものとして利用されています。
#!/bin/perl
であれば perl スクリプトになります。
bash を指定するので、bash スクリプトです。

sh や ksh 等ありますが、現在の POSIX に準拠したシェルは bash くらいなので、ここでは bash を利用します。
文字コード
文字コードは、基本的に ASCII であれば問題なく動きます。

UTF-8 を指定する場合でも、BOM (Byte Order Mark) やマルチバイト文字がなければ、実質上は ASCII と同じになるので問題なく動きます。

BOM を指定すると、スクリプトとしてはファイルの先頭に余計なバイナリが差し込まれることになります。
Kernel 側で実行を制御できなくなり、エラーで返るので注意してください。

また、マルチバイト文字も一部のコードが別な制御コードと混同されて、エラーを返すことがあります。
コメントであっても、できれば使わないに越したことはありません。

その点を認識して、注意してコメントを書くという運用を行うのであれば、問題にはならないと思います。
改行コード
文字コードには関係なく (ASCII でも UTF-8 でも EUC でも)、改行コードは LF である必要があります。

シェルスクリプトとして CR+LF を利用した場合は、実行エラーが発生します。

通常、実行するシステムでコーディングを行うことが多く、滅多に問題にはなりません。
外注した場合に改行コードの指定をうっかり忘れると、ほとんどの場合で Windows 端末によるコーディングが行われます。
動かないコードが納品される原因の上位に来るので、細かい点ですが注意しましょう。

FTP での ASCII 送信で、スクリプト単体を送信すれば改行コードが変換されて問題ないのですが、Zip にまとめて送るなどで取り切れないこともあります。
記述方法
テキストファイルなので、テキストエディタで記述します。

Linux なら vi / vim や nano, emacs, vscode 等で書けます。
Windows ではないので拡張子は何でも大丈夫、なんなら拡張子が無くても大丈夫ですが、慣例的に .sh や .bsh 等が使われています。

以下、最も簡単なサンプルとして xxxxx.sh を記述します。
#!/bin/bash
echo 'Hello World!'

実行方法

シェルスクリプトは、実行権限を与えて、コマンドとして利用します。

実行権限は、次のコマンドで与えることができます。
$ chmod +x xxxxx.sh
権限が付与できたら、次のように実行します。
$ ./xxxxx.sh
Hello World!
$ 
以下、実際に実行したところです。
サンプル スクリプト(実行権限あり)


また、実行権限を付与しなくても、シェルスクリプトとして実行する方法はあります。
サンプル スクリプト(実行権限なし)


これは、bash にスクリプトファイルを引数として読み込ませて、実行させているためです。

サンプルでは ./ を付けるものと付けないものがあり、なぜ分けているのか疑問に思われたでしょうか?

Linux / UNIX では、カレントディレクトリを示すのに . が利用されます。
カレントディレクトリのファイルを示すためには、ファイル名と区別する意味で / による階層構造を示す必要があります。

現在のディストリビューションでは $PATH にカレントディレクトリを示す . が含まれていません。
そのためカレントディレクトリにあるスクリプトは ./ がないとコマンドとして認識されません。

サンプル スクリプト(PATH指定なし)


これは、カレントディレクトリに ls 等のよく使うコマンド名でシェルスクリプトをホームディレクトリに配置されてしまうと、悪意あるコードを実行させることが容易になるからです。

シェルスクリプトの入門としては、以上のことに気を付ければ良いと思います。