シェルスクリプトの基礎 - ファイルとディレクトリ
概要
シェルスクリプトにおいて、ファイルとディレクトリに関する処理を記載する。
ファイルの存在を確認
ファイルが存在する場合
if文の演算子で、-eを使用することでファイルが存在することを確認することができる。
以下のシェルスクリプトでは、test.txtファイルが存在するか確認して、ファイルが存在する場合、File exists.と表示する。
#!/bin/bash
FILE="test.txt"
if [ -e $FILE ]; then
echo "File exists."
fi
ファイルが存在しない場合
上記と逆の場合、ファイルが存在しないことを確認する場合、演算子に!を付加することで結果を反転させることができる。
つまり、! -eと記述することで、ファイルが存在しない場合に真となる。
以下のシェルスクリプトでは、test.txtファイルが存在しない場合に、File not exists.と表示する。
#!/bin/bash
FILE="test.txt"
if [ ! -e $FILE ];then
echo "File not exists."
exit -1
fi
ディレクトリの存在を確認
ディレクトリが存在する場合
if文の演算子で、-dを使用することでディレクトリが存在することを確認することができる。
以下のシェルスクリプトでは、testディレクトリが存在する場合、Directory exists.と表示する。
#!/bin/bash
DIR="test"
if [ -d $DIR ];then
echo "Directory exists."
fi
ディレクトリが存在しない場合
上記と逆の場合、ディレクトリが存在しないことを確認する場合、演算子に!を付加することで結果を反転させることができる。
つまり、! -dと記述することで、ディレクトリが存在しない場合に真となる。
以下のシェルスクリプトでは、testディレクトリが存在しない場合に、Directory not exists.と表示する。
#!/bin/bash
DIR="test"
if [ ! -d $DIR ];then
echo "Directory not exists."
exit -1
fi
コマンドを使用した確認
ワイルドカードを指定してファイルおよびディレクトリを確認することができる。
ファイル名およびディレクトリ名にワイルドカードを指定して存在を確認する場合、以下のように記述する。(例 : txt拡張子を持つファイル等)
以下の例では、ls *.txt
コマンドは、txt拡張子のファイルが存在する場合、なんらかの文字列を返すため、if文の判定は真となる。
txt拡張子のファイルが存在しない場合、エラーが発生するので、/dev/null
にリダイレクトしている。
if ls *.txt > /dev/null 2>&1; then
echo "exists"
fi
その他の演算子
下表に、ファイルやディレクトリの存在を確認する際に、使用できる演算子を記載する。
表. 演算子
演算子 | 説明 |
---|---|
-a ファイル | ファイルがあれば真 |
-b ファイル | ファイルがありブロックス特殊ファイルであれば真 |
-c ファイル | ファイルがありキャラクター特殊ファイルであれば真 |
-d ファイル | ファイルがありディレクトリであれば真 |
-e ファイル | ファイルがあれば真 |
-f ファイル | ファイルがあり通常のファイルであれば真 |
-g ファイル | ファイルがありSGID(特殊なアクセス権)であれば真 |
-G ファイル | ファイルがあり実行グループIDによる所有者であれば真 |
-h ファイル | ファイルがありシンボリックであれば真(-Lと同じ) |
-k ファイル | ファイルがありステッキービットが設定されていれば真 |
-L ファイル | ファイルがありシンボリックであれば真(-hと同じ) |
-O ファイル | ファイルがあり実行ユーザIDによる所有者であれば真 |
-p ファイル | ファイルがあり名前付きパイプであれば真 |
-r ファイル | ファイルがあり読み取り可能であれば真 |
-s ファイル | ファイルがありサイズが0より大きければ真 |
-S ファイル | ファイルがありソケットであれば真 |
-t FD | FD(ファイルディスクリプタ)が端末でオープンされていれば真 |
-u ファイル | ファイルがありSUID(特殊なアクセス権)であれば真 |
-w ファイル | ファイルがあり書き込み可能であれば真 |
-x ファイル | ファイルがあり実行可能であれば真 |
ファイルの処理
ワイルドカードの使用
ワイルドカード(*)を使用して、カレントディレクトリ内のファイルを順に処理することができる。
以下の例では、全てのファイルを繰り返し処理している。
for FILENAME in *; do
echo "$FILENAME"
done
特定の拡張子を持つファイルのみを列挙する場合は、以下のように記述する。
以下の例では、全てのPNGファイルを繰り返し処理している。
for PNGFILE in *.png; do
echo "$PNGFILE"
done
また、次のように1行で記述することもできる。
for PNGFILE in *.png; do echo "$PNGFILE"; done
ワイルドカードを使用する場合、アスタリスク(*)をクォートの中に入れると、シェルによるワイルドカードの展開が行われない。
# 推奨する記述
## パス部分は安全にクォートされて、アスタリスクはワイルドカードとして機能する
rm -r "$HOME/.cache/"*
# 間違った記述
## アスタリスクがクォート内にあるため、*は文字列として扱われてワイルドカードとして機能しない
rm -r "$HOME/.cache/*"
## パスにスペースが含まれている場合、パスが正しく解釈されない
## また、変数が未定義の場合、意図しない動作につながる可能性がある
rm -r $HOME/.cache/*
findコマンドの結果の使用(再帰処理)
以下の例では、findコマンドで検索したファイルを、while文で順に処理している。 深い階層にあるファイルも再帰的に処理される。
find . -type f | while read FILENAME; do
echo "$FILENAME"
done
テキストファイルの読み込み
while文とreadコマンドを組み合わせて使用すると、テキストファイルの内容を1行ずつ処理できる。
このセクションでは、以下に示すlist.txtファイルを使用する。
# list.txtファイルの内容 one two three
テキストファイルを1行のみ読み込む
readコマンドは、ユーザからの入力の他に、ファイルからの入力を1行のみ読み込むことができる。
# 実行
read line < list.txt
echo "$line"
# 出力
AAA 100
標準入力へリダイレクトさせて読み込む
ファイルを標準入力へリダイレクトさせて、ファイル内容を1行ずつ読み込ませる。
以下の例では、list.txtファイルの内容を読み込み、1行ずつechoコマンドで表示させている。
# 実行
while read line
do
echo $line
done < ./list.txt
# 出力
one
two
three
ファイルを変数に格納して読み込む
ファイル内容をcatコマンドで表示させて、それを変数に格納し、ヒアドキュメントを使用して読み込む。
以下の例では、list.txtファイル内容を変数DATAに格納して、ヒアドキュメントを使用して変数の内容を読み込んでいる。
DATA=`cat ./list.txt`
while read line
do
echo $line
done << FILE
$DATA
FILE
# 出力
one
two
three
catコマンドでファイル内容を表示してパイプで渡す
ファイル内容をcatコマンドで表示させて、その結果をパイプを使用して読み込む。
以下の例では、lixt.txtファイルの内容をcatコマンドで表示させて、その結果をパイプでwhile readコマンドに渡している。
# 実行
cat ./list.txt | while read line
do
echo $line
done
# 出力
one
two
three