助け合いフォーラム

Essentials

Linux Essentials(Ver1.6)
問題ID : 2981
問題を開く
カレントディレクトリに以下のファイルがある。
 file01 file02 test01.txt test02.txt

以下のシェルスクリプトを実行したとき、画面に出力される結果として正しいものはどれか。

正解

解説

シェルスクリプトでは、構文「for」を用いて繰り返し処理を行うことができます。
for文の書式は以下の通りです。


設問では、カレントディレクトリのファイルのうち「file*」、すなわち「file01」「file02」に対してループ処理をしています。

echoコマンドは、指定された文字列を改行して出力します。

以上より正解は

です。

その他の選択肢は誤りです。

参考

【スクリプト】
GUI(Graphical User Interface)と比べた時のCUI(Character User Interface)の利点に、一連の手続きをファイルに保存し、自動化できる「スクリプト」があります。
スクリプト(script:台本、脚本など)とは、プログラムのように「人間がコードを書く」→「機械語へ翻訳する」→「実行」という段階を経ることなく、人間が書いたコードをそのまま実行することができます。
LinuxにはcshやBashなどのシェルがありますが、シェルに読み込ませるスクリプトを「シェルスクリプト」といいます。本項ではBashの構文を基に、スクリプトについて学習します。

●簡単なスクリプト
シェルスクリプトは、今までに覚えたコマンドを利用して作ることができます。
例えば、「ホームディレクトリへ移動し、ファイル一覧を表示する」というだけの一連の手続きをスクリプトにすると以下のようになります。

 #!/bin/bash
 cd ~/
 ls

この3行をファイル「home.sh」として保存し、「bash home.sh」と実行すると、記述した通りに実行されます。
シェルスクリプトでは、このような簡易なものだけでなく、複雑な処理も行うことができます。

【基本的な構文】
●シェバン(shebang)
先例「home.sh」の1行目は、Bashでスクリプトを実行する、という意味のおまじないで「シェバン(シバン、シェバング)」といいます。「#!」に続けてどのインタープリタ(シェルなどのプログラム)で実行するかを指定するもので、cshで動作させる場合は「#!/bin/csh」などと記述します。シェバンの記述がなくても動作はしますが、意図しない動作を防ぐために原則的には記述した方がよいでしょう。
なお、シェルスクリプトのファイル名は慣習的に「.sh」という接尾辞(suffix)を付与します。ただし「.txt」などと同様にOSに対しての意味はないため、「.sh」のつかないシェルスクリプトも存在します。

●変数
シェルスクリプトでは変数を扱うことができます。
変数への値の代入と値の参照は以下のように行います。

例)変数「var」へ文字列「Essentials」を代入する
 var="Essentials"
 ※変数と"="、値の間にスペースを入れてはいけません。

例)変数「var」の値を参照する
 $var
 「echo $var」などとすると、変数varの値が標準出力へ出力されます。

●引数
シェルスクリプトでは引数を扱うこともできます。
引数の数は「$#」、引数は先頭から「$1」「$2」などと参照できます。
例)スクリプトで引数を扱う


●繰り返し(ループ)処理
シェルスクリプトでは、例えば「カレントディレクトリのにある全てのテキストファイル *.txt をすべてコピーしたい」というような場合、処理をループ(繰り返し)で行うことができます。
以下は、forを使ったループ処理の書式です。

 ※do~doneまではループ内の処理なので、通常は(読みやすさのために)スペースまたはタブで文字下げします。

「変数」には、「値のリスト」にある値が一つずつ代入され、処理を行います。
例えば、カレントディレクトリに「a.txt」「b.txt」「c.txt」が存在する場合、for文を使って以下のように処理することができます。

例)カレントディレクトリにある「.txt」で終わるファイルすべてをコピーする

変数「$text」には「a.txt」「b.txt」「c.txt」が順に代入され、do~doneの処理「cp $text $text.cp」が実行されます。したがって、本処理が実行されると「a.txt.cp」「b.txt.cp」「c.txt.cp」というファイルが作成されます。

●終了ステータス(リターンコード)
Linux(Unix)のコマンドは、コマンドの実行結果を終了ステータス(リターンコード)で返すという仕組みが組み込まれています。
例えば「ls」とコマンドを実行すると、カレントディレクトリにあるファイル一覧が表示されてコマンドが終了します。直後にechoコマンドで「$?」という変数を表示すると、終了ステータスを参照することができます。

例)終了ステータスを参照する
 $ ls
 file1.txt file2.txt
 $ echo $?
 0

変数「$?」には、直前に実行したコマンドの終了ステータスが格納されます。
終了ステータスは以下の意味を持ちます:
・コマンドが正常終了したとき ... 0
・コマンドが異常終了したとき ... 1~255

lsコマンドで存在しないファイルを指定した際はエラーになりますが、終了ステータスを参照すると以下のようになります。
例)終了ステータスを参照する(コマンドが異常終了した時)
 $ ls file.txt
 ls: cannot access file.txt: No such file or directory
 $ echo $?
 2

終了ステータスがどのような意味をもつのかは、manまたはinfoコマンドのマニュアルに書かれていることがあります。

終了ステータスを活用すると、コマンドの実行結果次第で処理を分岐させることもできます。
例えば、分野「コマンドラインの基本」で学習したメタキャラクタに以下のようなものがあります:
・コマンド1 && コマンド2 ... コマンド1が成功した場合、コマンド2を実行
・コマンド1 || コマンド2 ... コマンド1が失敗した場合、コマンド2を実行
この「&&」「||」はいずれもコマンド1の終了ステータスを判断しています。
メタキャラクタはシェルスクリプトでも利用できますので、以下のような処理を書くこともできます。

例)ディレクトリを作成し、成功した場合にファイルを移動させる
 mkdir tmp && mv *.txt tmp

例)ディレクトリを作成し、失敗した場合はエラーメッセージを表示する
 mkdir tmp || echo "mkdir error"

●実行方法
シェルスクリプトを実行するには以下の方法があります。
・実行権を付与して実行
・bashコマンド または sourceコマンドの引数に渡して実行

・実行権を付与して実行
Linux(Unix)のファイル・ディレクトリには以下の三つの権限が付与されています。
 読み取り権(r:read) ... 参照することができる
 書き込み権(w:write) ... 書き込み・更新することができる
 実行権(x:execute) ... 実行することができる
※権限(パーミッション)の詳細は、分野「ファイルのパーミッションと所有権を管理する」にて学習します。

ファイル・ディレクトリに与えられている権限は、コマンド「ls -l」で確認することができます。


実行権が付与されたファイルは、lsコマンドなどと同様にファイルをコマンドとして扱うことができるようになります。
ただし、環境変数PATHに設定されていないディレクトリのスクリプトを実行する際は、パスを指定することを忘れないでください。
例えばディレクトリ「/home/user01/bin」へ保存したスクリプト「home.sh」を実行するには以下の方法があります。

例)実行権が付与されたスクリプト「home.sh」を実行する
○絶対パスを指定して実行
 $ /home/user01/bin/home.sh
○ディレクトリを移動して相対パスで実行
 $ cd /home/user01/bin
 $ ./home.sh
○環境変数PATHに「/home/user01/bin」を追加して実行
 $ export PATH="/home/user01/bin:$PATH"
 $ home.sh
※環境変数PATHについては、分野「コマンドラインの基本」を参照してください。

なお、実行権が与えられていない場合に上記のように実行すると、エラーが出力されて実行できません。
例)実行権が与えられていないスクリプトを実行する
 $ ./script.sh
 -bash: ./script.sh: Permission denied
 → Permission denied=権限が不正 という理由のエラーになる

・bashコマンド または sourceコマンドの引数に渡して実行
コマンドbashやsourceは、引数に指定されたファイルを実行します。
例)スクリプト「home.sh」を実行する
 $ bash home.sh
 $ source home.sh

この時のスクリプトには、実行権が付与されている必要はありません。

sourceコマンドとbashコマンドには以下のような違いがあります。
・sourceコマンド ... 指定したシェルスクリプトを読み込み、現在のシェルで実行する。スクリプトで設定した変数はシェル変数として現在のシェルで参照される。また、現在のシェルに設定しているシェル変数もスクリプトで参照される
・bashコマンド ... シェルを起動してシェルスクリプトを実行する。スクリプトで設定した変数はスクリプト内(起動したシェル内)で完結し、現在のシェルに設定しているシェル変数もスクリプトへ反映されない

以下は、sourceコマンドとbashコマンドの実行例です。
例)シェル変数SAMPLEの扱い

なお、環境変数はsource、bashに関わらず参照されます。

上に戻る

正解が誤りの可能性(すべて表示されるはず?)

公開日 2022/12/14

環境:Ubuntuにて同様の結果を確認したら、file01,02の.txtを含めた全ファイルが表示されました。

2022/12/14 21:11

Kali Linuxで実行しましたが、正答の通りの結果でした。

for f in file*
で、"file" で始まるファイルのみを抽出しているので
test01.txt と test02.txt は出力されないと思いますが、いかがでしょうか。


コメント

この返信に対して
コメントを記入できます

この投稿に対して返信しませんか?