シェル スクリプト ファイル存在チェック・空のファイルチェック

バイオインフォ道場、くまぞうです。

Bashでスクリプトを作成するときに、よく使うのがファイルの存在チェックです。if文と組合せると、ファイルの有無によって処理を分けることができます。エラー処理も記述できて使いやすいスクリプトになります。様々な処理で活用できるので、是非参考にしてみて下さいね。

スポンサーリンク



ファイルの存在チェック

ファイルのチェックといえば、代表例は「ファイルがあるか?」ですよね。存在すれば、次の処理を実行します。存在しなければ、「指定したファイルがないよ」というエラーを表示してあげると便利です。

オススメ記事
sed 便利な文字列処理(空白文字の整理・空白行の削除)
awk 複数行の処理
awk split 文字列分割 使い方

テストコマンドで真偽を判定する

「ファイルがあるか?」というチェック(評価)は、テストコマンド(test)で調べることができます。テストコマンドは、与えられた条件式の真偽を判定するコマンドです。以下の例 check_file.sh の場合、条件式は「-e file」の部分です。「ファイルが存在するか?」をチェックしています。-eの部分を変えると色々なことを調べることができます(後述)。if文と組合せて、評価に応じて処理を分岐させています。また、テストコマンドは[ ]を使って省略できます。こちらの表記の方が分り易いですよね。

check_file.sh

#! /bin/bash

if test -e "aaa.txt"; then # aaa,txtはあるか?
    echo "aaa.txt found."
else
    echo "aaa.txt NOT found."
fi
$ chmod +x check_file.sh
$ touch aaa.txt # 空のaaa.txtを作ります
$ ./check_file.sh
aaa.txt found.

if 文で処理を分岐する

if文を使うと、「条件が成立した場合(if)」・「条件が成立しなかった場合(else)」に分けて、処理を分岐させることができます。例として、テストコマンドの省略形([ ])とif文を組み合わせてみました。

check_file.sh(省略版)

#! /bin/bash

if [ -e "aaa.txt" ]; then # aaa,txtはあるか?
    echo "aaa.txt found."
else
    echo "aaa.txt NOT found."
fi

関連記事
シェルスクリプト Hello World スクリプトの書き方
シェルスクリプト if 単純な条件分岐 スクリプトの書き方
シェルスクリプト testコマンド 条件評価 スクリプトの書き方

人気記事
シェルスクリプト 文字列処理(部分文字列・置換・長さ・連結・分割)
シェルスクリプト select メニューを作る スクリプトの書き方
シェルスクリプト 関数 スクリプトの書き方

ファイルの評価

ファイルチェック用の評価演算子で、代表的なものをまとめてみました。テストコマンドに、与える条件式[ -評価演算子 file ]評価演算子を変えることで色々なことを調べることができます。以下の例では、ファイルが空かどうか?を調べています(あまり実用性はないかもしれません)。

  • -a file
    fileが存在する
  • -e file
    fileが存在する(-aと同じ)
  • -d file
    fileが存在し、且つ、ディレクトリ
  • -f file
    fileが存在し、且つ、通常のファイル
  • -L file
    fileが存在し、且つ、シンボリックリンク
  • -r file
    fileが存在し、読み取り可能
  • -s file
    fileが存在し、空ではない
  • -w file
    fileが存在し、書き込み可能
  • -x file
    fileが存在し、実行可能(ディレクトリなら検索可能)
  • fileA -nt fileB
    fileAがfileBよりも新しい
  • fileA -ot fileB
    fileAがfileBよりも古い

check_empty.sh

#! /bin/bash

if [ -s "aaa.txt" ]; then
    wc -l aaa.txt
else
    echo "aaa.txt is empty."
fi
$ chmod +x check_empty.sh
$ rm aaa.txt     # aaa.txtを削除
$ touch aaa.txt  # aaa.txtを生成(空ファイル)
$ ./check_empty.sh
aaa.txt is empty.

$ echo "hello!" > aaa.txt
$ cat aaa.txt
hello!

$ ./check_empty.sh #「書き込みあり」にて処理が分岐した
1 aaa.txt

評価を組み合わせる

チェックは複数の条件を組み合わせることの方が多いです。条件を分けて書く場合と、式を組合せて書く場合があります。用途に応じて使い分けます。一般的に、分けて書いた方が分り易いですが、スクリプトがダラダラ長くなるのが難点です。条件を簡潔に表現できるならば、式を組み合わせる方が管理がしやすくなるかもしれません。ただし、条件設定が抜けやすくなるので注意しましょう。

式を組み合わせる場合は、&&(AND)、||(OR)を使います。同様に、-a(AND)、-o(OR)を使って書く方法もあります(後述)が、書式が微妙にことなるので注意しましょう。どちらかに統一して使う方が良いでしょう。

check_empty2.sh(条件を分けて書く)

#! /bin/bash

if [ -e "aaa.txt" ]; then       # ファイルの存在確認
    echo "aaa.txt found."
    if [ ! -s "aaa.txt" ]; then # 空かをチェックする
	echo "but empty!"
    fi
else
    echo "aaa.txt NOT found."
fi

check_empty2.sh(式を組合せて書く)

#! /bin/bash

MY_FILE=$1

if [ -e ${MY_FILE} ] && [ ! -s ${MY_FILE} ]; then # 存在、且つ、空のチェック
    echo "aaa.txt found. but empty!"
else
    echo "" # 空でないファイルがあるかもしれないし、ファイルがないかもしれないし...
fi

テストコマンドを使わないファイル確認

テストコマンドを使わなくてもファイル確認をすることができます。複数のファイルをチェックしてみます。工夫次第ですね。

check_file2.sh(テストコマンドを使わない)

#! /bin/bash

EXT=$1

if ls *.${EXT} > /dev/null 2>&1; then
    echo "${EXT}:exist."
else
    echo "${EXT}:not exist."
fi
$ chmod +x check_file2.sh
$ check_file2.sh txt
txt:exist

テストコマンドを書くときの注意

細かい注意点があるのでまとめます。自分でスクリプトを作成する場合は注意しましょう!

  • テストコマンドを[ ]で記載する場合、スペースを空けることに注意する。
    【NG】if [-e file]; then   # [ ] の横にスペースがない!
    【OK】if [ -e file ]; then # [ ] の横にスペースが必要
    【OK】if [ ! -e file ]; then # 否定(!)の場合もスペースに注意
  • 組み合わせるとき、&&を使う場合と-aを使う場合は書き方が異なる(OR:||, -oも同じ)。
    【OK】if [ -e file ] && [ -s file ]; then # 複数の条件を分けて書く
    【OK】if [ -e file -a -s file ]; then     # 複数の条件をひとくくりに書く
  • if文のthenを同じ行に書くか、別の行に書くかを統一する。(同一行の場合は;が必要)
    【OK】if [ -e file ] && [ -s file ]; then # 同じ行なら、thenの前に;
    【OK】if [ -e file -a -s file ]
         then                                   # 次の行なら、;は不要

参考書籍

シェルスクリプトを書く際に、if文やテストコマンドが使えるようになると応用範囲が広がります。エラー処理を考慮しやすくなるからです。今回は、ファイルの存在チェックを例にif文とテストコマンドを使ってみました。自分のシェルスクリプトに、ファイルが存在するときと存在しないときの処理を入れるだけで、より使いやすいスクリプトへと改良することができると思います。テストコマンドには、ファイルの属性に関するもの以外にも色々な評価演算子があります。どんどん使ってみましょう!スクリプトを書くのが、もっと楽しくなるかもしれませんね!

スポンサーリンク