スクリプトを実行するためにパターンに一致するファイルがあるかどうかをテストします。

スクリプトを実行するためにパターンに一致するファイルがあるかどうかをテストします。

if特定のパターンに一致するファイルがあるかどうかをテストするステートメントを作成しようとしています。ディレクトリにテキストファイルがある場合は、指定したスクリプトを実行する必要があります。

私の現在のコード:

if [ -f /*.txt ]; then ./script fi

.txtいくつかのアイデアをください。ディレクトリにある場合にのみスクリプトを実行したいと思います。

答え1

[ -f /*.txt ]

存在する場合のみ true を返します。一つ/(そして単一の)名前で終わり、.txt通常のファイル、または一般的なファイルへのシンボリックリンクである隠しファイル。

[これは、ワイルドカードがコマンド(ここ)に渡される前にシェルによって拡張されるためです。

/a.txtしたがって and があれば/b.txt、 、 and 5 つの[パラメータが渡されます。これはあまりにも多くのパラメータが与えられたと不平を言うでしょう。[-f/a.txt/b.txt][-f

*.txtパターンが1つ以上の非表示ファイル(通常または非正規)に拡張されていることを確認するには、bashシェルで次の操作を行います。

shopt -s nullglob
set -- *.txt
if [ "$#" -gt 0 ]; then
  ./script "$@" # call script with that list of files.
fi
# Or with bash arrays so you can keep the arguments:
files=( *.txt )
# apply C-style boolean on member count
(( ${#files[@]} )) && ./script "${files[@]}"

shopt -s nullglob具体的ですがbashshoptはい、nullglob実際にはから由来zsh)、、、、のようなシェルにはksh93同じzshyashtcshあります。

そしてzsh、テストはパターンに一致するファイルはありますか?これは、匿名関数とN(for nullglob)とY1(最初のルックアップ後に停止)glob修飾子を使用して作成できます。

if ()(($#)) *.txt(NY1); then
  do-something
fi

これらのファイルはディレクトリの内容を読み取ってこれらのファイルを見つけ、ファイルにまったくアクセスしようとしないため、シェル計算ファイルのリストなどのlsコマンドを呼び出すよりも効率的なソリューションになります。stat

標準にsh対応するものは次のとおりです。

set -- [*].txt *.txt
case "$1$2" in
  ('[*].txt*.txt') ;;
  (*) shift; script "$@"
esac

問題は、Bourne または POSIX シェルの場合、パターンが一致しない場合、それ自体が拡張されることです。だから*.txtに拡張すると、ディレクトリにファイルがない*.txtためか.txt、または*.txt。使用すると、[*].txt *.txt2つを区別できます。

*.txtこれで少なくとも1つと一致することを確認するには定期的なファイルまたは一般ファイルへのシンボリックリンク(提案どおり[ -f *.txt ])または一致するすべての*.txtファイル定期的なファイル(シンボリックリンク解決後)は別の話です。

そしてzsh

if ()(($#)) *.txt(NY1-.); then
  echo "there is at least one regular .txt file"
fi
if ()(($#)) *.txt(NY1^-.); then
  echo "there is at least one non-regular .txt files"
fi

-シンボリックリンクが解決される前にテストする場合は削除します。つまり、シンボリックリンクが通常のファイルを指しているかどうかに関係なく、非正規ファイルとして扱います。)

答え2

考えられる解決策はBash組み込みですcompgen。このコマンドは、一致するファイルがあるかどうかを示す終了コードとともに、ワイルドカードパターンに一致するすべてのエントリを返します。

compgen -G "/*.text" > /dev/null && ./script

より速い解決策を探している間、私はこの質問を見つけました。

答え3

いつでも以下を使用できますfind

find . -maxdepth 1 -type f -name "*.txt" 2>/dev/null | grep -q . && ./script

説明する:

  • find .: カレントディレクトリの検索
  • -maxdepth 1: サブディレクトリを検索しません。
  • -type f:一般ファイルのみ検索
  • name "*.txt":次に終わるファイルの検索.txt
  • 2>/dev/null:エラーメッセージを次にリダイレクトします。/dev/null
  • | grep -q .:任意の文字をgrepし、文字がない場合はfalseを返します。
  • && ./script./script前のコマンドが成功した場合にのみ実行されます(&&)

答え4

Chazelasが指摘したように、ワイルドカード拡張が2つ以上のファイルと一致すると、スクリプトは失敗します。

しかし、私はトリックを使用しました(あまり好きじゃなくても)バイパス:

PATTERN=(/*.txt)
if [ -f ${PATTERN[0]} ]; then
...
fi

どのように動作しますか?

ワイルドカード拡張はファイル名の配列と一致し、ファイル名がある場合は最初のファイル名を取得し、一致がない場合はnullを取得します。

関連情報