シェルスクリプトのファイル存在判定でワイルドカードを使いたい



ファイル判定で以下のように書くと
「unexpected operator」とエラーになります。

if [ -f /path/*.txt ]; then
echo "OK"
fi


以下のように書けばエラーにならない
if [ -f /path/hoge.txt ]; then
echo "OK"
fi

ワイルドカードを使って1つもファイルがないか、あるいは1つでもファイルがあるかを判定したいのですが、
どう書いたら良いでしょうか。

回答の条件
  • 1人1回まで
  • 登録:
  • 終了:2015/05/14 10:42:28
※ 有料アンケート・ポイント付き質問機能は2023年2月28日に終了しました。

ベストアンサー

id:JULY No.1

回答回数966ベストアンサー獲得回数247

ポイント68pt

ワイルドカードが先に展開されて test コマンド(if [ ~ の "[" の実体)の引数になってしまうので、期待した動作にならないはずです。

sh -x スクリプトファイル名

とすれば、その様子が分かると思います。

で、単純に ls コマンドの戻り値を使う方法が考えられます。

ls /path/*.txt >/dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "No match"
else
    echo "At least one file"
fi
id:a-kuma3

コマンドの戻り値を使う場合には、普通、こう書きます。

if ls path/*.log > /dev/null 2>&1
then
    echo "OK"
else
    echo "NG"
fi

# 説明のために、敢えて冗長に書いたのであれば失礼をご勘弁

2015/05/13 19:18:18
id:spacewarp

おお、スマートな方法ですね。参考になります

2015/05/14 10:40:42

その他の回答2件)

id:JULY No.1

回答回数966ベストアンサー獲得回数247ここでベストアンサー

ポイント68pt

ワイルドカードが先に展開されて test コマンド(if [ ~ の "[" の実体)の引数になってしまうので、期待した動作にならないはずです。

sh -x スクリプトファイル名

とすれば、その様子が分かると思います。

で、単純に ls コマンドの戻り値を使う方法が考えられます。

ls /path/*.txt >/dev/null 2>&1
if [ $? -ne 0 ]; then
    echo "No match"
else
    echo "At least one file"
fi
id:a-kuma3

コマンドの戻り値を使う場合には、普通、こう書きます。

if ls path/*.log > /dev/null 2>&1
then
    echo "OK"
else
    echo "NG"
fi

# 説明のために、敢えて冗長に書いたのであれば失礼をご勘弁

2015/05/13 19:18:18
id:spacewarp

おお、スマートな方法ですね。参考になります

2015/05/14 10:40:42
id:a-kuma3 No.2

回答回数4973ベストアンサー獲得回数2154

ポイント66pt

ファイルとディレクトリを判定したいとか、読み込み可能か、など test コマンドのパラメータをフルに使いたければ、シェルの関数を書いてあげる感じになります。

#	引数で指定されたファイルがあるかどうかを確認する関数

is_file_exist() {
    for f in $*
    do
        if [ -f $f ]
        then
            return 0
        fi
    done
    return 1
}


#   こうやって使います

if is_file_exist path/*.txt
then
    echo "OK : txt"
else
    echo "NG : txt"
fi

# 使う方で [] がないのは、間違いじゃないですよ :-)

id:spacewarp

ループで取ればいいんですね。なるほど

2015/05/14 10:41:29
id:richmikan No.3

回答回数1ベストアンサー獲得回数0

ポイント66pt

ワイルドカードは、該当ファイルが存在すれば元の文字列が変化しますが、存在しなければ元の文字列そのままになるので、AWKを使って文字列が変化した(=該当ファイルがあった)ら"OK"を表示する、というスクリプトを書いてみました。

echo /path/*.txt | awk '$0!="/path/*.txt"{print "OK";}'

ちなみに、AWKの動作をprintではなくてexitにすれば後のシェルスクリプトで分岐させることもできます。

(a)case文で

echo /path/*.txt | awk '{exit ($0!="/path/*.txt")?0:1;}'
case $? in
  0) echo "OK";;
  *) echo "NG";;
esac

(b)if文で

echo /path/*.txt | awk '{exit ($0!="/path/*.txt")?0:1;}'
if [ $? -eq 0 ]; then
  echo "OK"
else
  echo "NG"
fi
id:spacewarp

いろんな書き方がありますね。
ありがとうございます。

2015/05/14 10:42:05

コメントはまだありません

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

回答リクエストを送信したユーザーはいません