find -name
sh
私のスクリプトで使用しようとしています。以前に計算された条件の複雑な引数。単純化すると、
cond="-name '*.txt*"
find . $cond -ls
しかし、今私が経験している問題は、のワイルドカードが呼び出さ$cond
れる前にシェルによって拡張されるかfind
。find
これをテストするために、空のテストディレクトリで次のことを行いました。
touch a.txt b.txt c.dat
それから繰り返し
cond="-name '*.txt'"; echo $cond; find . $cond
$cond
私が考えることができるすべての種類の引用/エスケープを使用して異なる値を使用します。
.
4つのエントリ(ディレクトリを含む)がすべて取得されましたが、ファイルが見つからないか不明な基本またはオペレータfind
というメッセージが表示されます。b.txt
もちろん、正しい出力は2つのテキストファイルでなければなりません。
どのようなヒントがありますか?私は基本的なものを見逃していると確信しています。
答え1
Bourneに似たシェル(除外zsh
)では、リストコンテキストで引用されていない変数拡張を維持することは次のとおりです。分割+グローバルオペレーター。存在する:
cond="-name '*.txt'"; echo $cond
の内容は、$cond
まず$IFS
特殊変数の値に基づいて分割されます。デフォルトでは、ASCII スペース、タブ、改行文字です。
だからそれは分けるを入力-name
して'*.txt'
。それから全体的な状況部分的に適用されます。すべて性格ワイルドカード文字が含まれている場合(*
ここで2番目の文字)、単語はパターンに一致するファイルのリストに展開されるか、一致するファイルがない場合は変更されずに残ります。したがって、一致するファイルが存在しない場合は、現在のディレクトリで名前が終わるか拡張されるファイルのリストが展開されます'*.txt'
。'
.txt'
'*.txt'
この単語リストは別の引数としてに渡されますecho
。一致するファイルがない場合、および3echo
つの引数が受け取ります。"echo"
"-name"
"'*.txt'"
もちろん、find
コマンドにも同様に適用されます。
コマンドはパラメータsumをfind
受け取りたいので、調整する必要があります。-name
*.txt
分割+グローバルオペレーター。
$IFS
で使用する区切り文字と一致する値が必要です$cond
。たとえば、
cond='-name:*.txt'
IFS=':'
そしてあなたは望んでいません。全体的な状況~の一部分割+グローバル演算子なので、次の方法で無効にする必要があります。
set -f
だからそれは次のようになります:
cond='-name:*.txt'
IFS=:; set -f
find . $cond -ls
またはこれを行うこともできます:
cond='-name *.txt'
set -f
find . $cond -ls
そして、$IFS
デフォルト値が変更されていないと仮定します。
あるいは、シェルが配列をサポートしている場合は、スカラー変数に依存し、拡張時にシェルが配列を分割することを期待する代わりに、配列を使用できます。
これはksh93
、または次mksh
に適用されます。bash
zsh
cond=(-name '*.txt') # an array with two elements: "-name" and "*.txt"
find . "${cond[@]}" -ls # elements of the array expanded as separate arguments
# to find.