Bash if条件で単純なワイルドカード式に一致するファイルが存在するかどうかを確認できますか? [コピー]

Bash if条件で単純なワイルドカード式に一致するファイルが存在するかどうかを確認できますか? [コピー]

愚かなことは、スクリプトで次の条件文を引き続き使用することです。

if [ $(ls FOO* 2> /dev/null) ] # if files named "FOO*" were downloaded 
then
    echo "Files found" 
    # ... process and email results
else
    echo "Not found"
    # ... email warning that no files were found (against expectations)
fi

これは以下に適用されます。0と1のファイル無名FOO*だが複数の場合は失敗。ログにいくつかの異なるエラーメッセージが見つかりました。

[: FOO_20131107_082920: unary operator expected
[: FOO_20131108_070203: binary operator expected
[: too many arguments

私の質問は:Bash条件付きでif正しいことを確認する方法は?1つ以上その名前で始まるファイルはFOO存在しますか?

GNU bash、バージョン 4.2.25(1)-リリース(x86_64-pc-linux-gnu)

ベストアンサー1

これは、lsへのコマンドが出力を空白に置き換えてに渡される前にトークン化を受けるために発生します[。壊れない方法は、ファイルを配列に配置してから、配列に少なくとも1つのメンバーがあることを確認することです。

shopt -s nullglob

files=( FOO* )
if (( ${#files[@]} )); then
    # there were files
fi

((これは、デフォルトでは、値が0以外の場合はtrueを返し、配列内のエントリの${#files[@]}数(globに一致するファイルがある場合は> 0)を取得するために機能します。

設定されていない限り、nullglob次のこともできます。

if ls FOO* >/dev/null 2>&1; then
    # there were files
fi

lsこれは、存在しないファイル名を渡す場合(文字通りFOO*、一致するファイル名がない場合はその終了コードが1になる終了コードを確認します。もちろん、ユーザーが邪悪で名前がファイル名のFOO*場合を除く)、0を返します。 :-) ))。

これら2つはディレクトリとも一致します。本当に一般的なファイルのみを一致させるには、以下をテストする必要があります。

for file in FOO*; do
    if [[ -f $file ]]; then
        # file found, do some stuff and break
        break
    fi
done

おすすめ記事