
file1.c
ファイルfile2.c
とfile3.c
。コマンドfind
出力:
$find -name "*.c"
./file1.c
./file2.c
./file3.c
find
それから引用符なしで使用したいと思います.*c
。set -f
$echo $- # check current options
himBHs
$set -f
$echo $- # check that f option is set
fhimBHs
$find -name *.c
./file1.c
./file2.c
./file3.c
$set +f # unset f option
次の関数で同じコマンドを試しました.bashrc
。
find() {
set -f
eval command find $@
set +f
}
ただし、テストするとエラーが発生します。
$ . ~/.bashrc && find -name *c
find: paths must precede expression: file1.c
Usage: find [-H] [-L] [-P] [-Olevel] [-D help|tree|search|stat|rates|opt|exec] [path...] [expression
関数でこのエラーが発生するのはなぜですか?find
バージョン: GNU 4.6.0
答え1
言っていませんが、次のように関数を呼び出す必要があります。
find -name *.c
ただし、ワイルドカードが閉じられていないため、*.c
呼び出し前にシェルが拡張されます。したがって、find
コマンドには「-name」とそれに続く3つのパラメータ(エラーメッセージ)が表示されます。
引用符の代わりにバックスラッシュを使用できます。
find -name \*.c
答え2
関数はファイル名ワイルドカードを無効にしますが、シェル拡張ワイルドカードを使用して呼び出します(ファイル名ワイルドカードはいいえ呼び出したシェルで閉じます。)
つまり、コマンドのグローブ
find -name *c
find
関数を呼び出す前に拡張してください。これにより、find
ユーティリティが理解できない内部関数呼び出しが発生します。
引用符付き引数を使用して関数を呼び出すと、この問題を解決できます。
find -name "*c"
ただし、この機能はすでに入力したコマンドをコピーするだけなので、まったく役に立ちません。
存在する次へ追加それは役に立たず、間違っています。$@
コードで引用されていないため、(デフォルトでは)スペースにパラメータを分割します。これはあなたを意味しますできないたとえば、使用します。
find -name "* *"
スペースを含む名前を見つけます。
また、何らかの理由でeval
シェルが$@
。これは意味する
find -name '$(echo hello)'
名前がありますが見つかりませ$(echo hello)
んhello
。
もう一つは、シェルを呼び出すとすでにを使用するset -f
と、その機能は無効になります。
便利な関数を作成しましょう。見つける関数数量ファイル名パターン(例:
myfind "*.c" "*.txt" "* *"
.c
上記のコマンドがまたはで終わり、スペースを含む.txt
パス名を返したいです。
機能は次のとおりです。
myfind () {
# Replace each positional parameter "$pattern"
# with -o -name "$pattern"
for pattern do
set -- "$@" -o -name "$pattern"
shift
done
shift # shift off the initial "-o"
find . "$@"
}
上記の関数を呼び出すと、最終的に実行されます。
find . -name '*.c' -o -name '*.txt' -o -name '* *'
配列をリストとして使用する方が簡単で、もう少しbash
入力しても問題ありません。
myfind () {
local -a args
# Build the argument list for find by adding
# -o -name "$pattern"
# for each positional parameter
for pattern do
args+=( -o -name "$pattern" )
done
args=( "${args[@]:1}" ) # remove the initial "-o"
find . "${args[@]}"
}