指定した通常ファイルの存在確認

shell script preprocess 3/N

公開日: 2021-02-18
更新日: 2024-04-15

  Table of Contents

Case 1: ifを用いるケース

if command syntax

1
2
3
if [[ expression ]]; then
    command
fi
  • [[ expression ]]の終了値が 0 であれば commandが実行される
  • 終了値が 0 でなければ, commandを実行することなくif文を終了

ファイルの存在判定は, -e, -f を用いますが以下のような違いがあります:

  • -e: ファイルが存在すれば真
  • -f: ファイルが存在し, 通常ファイルならば真

従って, x.txtというファイルが存在するかどうか調べたい場合は,

1
2
3
4
5
6
7
8
9
10
11
# fileが存在するときに処理を走らせたい場合
if [[ -f x.txt ]] ; then
    echo file exists.
    exit 0
fi

# fileが存在しないときに処理を走らせたい場合
if [[ ! -f x.txt ]] ; then
    echo 'File "x.txt" is not there, aborting.'
    exit 1
fi

なぜ二重に [[ expression ]] で囲うのか?

bashにおける挙動上の差異

  • 変数をダブルクォートで囲う必要性の有無
  • escapeの必要性の有無
  • &&, || というand条件, of条件記号の利用可能性
  • =~によるregex matchingの利用可能性

基本的には, [[ ... ]]を用いることが推奨されています.

1
2
3
4
5
6
# 変数をダブルクォートで囲う必要性の有無
file="file name"
[[ -f $file ]] && echo "$file is a regular file"

file="file name"
[ -f "$file" ] && echo "$file is a regular file"

複数条件を取り扱う際, 優先順番を明確にする ( ... ) は single square bracketだと, escapeする必要がありますが, 二重だとescapeする必要がなくなり, 書き方が以下のようにコンパクトになります.

1
2
3
4
# escapeの必要性とand/or条件
[[ -f $file1 && ( -d $dir1 || -d $dir2 ) ]]

[ -f "$file1" -a \( -d "$dir1" -o -d "$dir2" \) ]

また, regexを用いた文字列パターンマッチングも可能になるというメリットもあります.

1
2
# regex expresionの利用可能性
[[ $(date) =~ ^Fri\ ...\ 13 ]] && echo "It's Friday the 13th!"

個人的にsingle square bracketの一番イヤな点は, 比較処理の場合です.

  • x > y: x is greater than or equal to y
  • x \> y: x is strictly greater than y
1
2
3
4
5
6
7
# 以下の場合は, condition passed が表示される
a=1
[ "$a" > 1 ] && echo "condition passed"

# 以下の場合は, condition passed が表示されない
a=1
[[ "$a" > 1 ]] && echo "condition passed"

Case 2: find コマンドを用いるケース(推奨)

1
2
3
4
5
6
7
8
9
10
11
% tree -L 1 -a
.
├── bin             # direcory
├── Desktop         # direcory
├── Documents       # direcory
├── Downloads       # direcory
├── hexaly_setup    # direcory
├── Music           # direcory
├── .zshenv         # file
├── .zshrc          # file
└── .zshrc.backup   # file

というカレントディレクトリ構成に対して, zsh という文字列を含むファイルが存在するならば conditioned passedがターミナル上に出力させたいとします.

1
2
3
4
5
6
7
$ find ./ -maxdepth 1 -name ".zsh*" -type f -exec bash -c "echo conditioned passed" {} +
conditioned passed

$ find ./ -maxdepth 1 -name ".zsh*" -type f -exec bash -c "echo conditioned passed" {} \; 
conditioned passed
conditioned passed
conditioned passed
  • findコマンドの-exec bash -cfindで見つけたファイル or direcotryに対して実行するスクリプトを指定
  • {}は, findコマンドで見つけたオブジェクトの引数で呼ぶ際の位置
  • \;, +の差分は, 前者が逐次実行, 後者は検索結果をすべて一括の一つのスクリプトで同時に処理する場合に用いる

References



Share Buttons
Share on:

Feature Tags
Leave a Comment
(注意:GitHub Accountが必要となります)