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
具体的ですがbash
(shopt
はい、nullglob
実際にはから由来zsh
)、、、、のようなシェルにはksh93
同じzsh
文yash
がtcsh
あります。
そして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 *.txt
2つを区別できます。
*.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
説明する:
答え4
Chazelasが指摘したように、ワイルドカード拡張が2つ以上のファイルと一致すると、スクリプトは失敗します。
しかし、私はトリックを使用しました(あまり好きじゃなくても)バイパス:
PATTERN=(/*.txt)
if [ -f ${PATTERN[0]} ]; then
...
fi
どのように動作しますか?
ワイルドカード拡張はファイル名の配列と一致し、ファイル名がある場合は最初のファイル名を取得し、一致がない場合はnullを取得します。