find
次の最小作業例を使用して関数に入れ、関数に渡された引数をキャプチャしてみました。
機能DO { ls $(find .-type f -name "$@" -exec grep -IHl "TODO" {} \;) }
ただし、実行すると、DO *.tex
「find:path must beforeexpression:」が表示されます。しかし、私が直接これを行うと、次のようになります。
ls $(find .-type f -name "*.tex" -exec grep -IHl "TODO" {} \;)
その後、「TODO」を含むすべてのTeXファイルを取得します。
DO
関数でたくさん試しました。たとえば、、、\"$@\"
引用符'$@'
を変更しましたが、動作はまだ同じです。
それでは、関数内で作業を強制的に見つけるにはどうすればよいですか?
答え1
コードにはいくつかの問題があります。
パターンが現在のディレクトリのファイル名と一致する場合、
*.tex
この関数が呼び出されるとパターンが拡張されます。この関数を呼び出すときは、DO
パターンを'*.tex'
、"*.tex"
またはで参照する必要があります。\*.tex
不要
ls
。すでに両方があり、find
見つかったgrep
ファイルのパス名を報告できます。-name "$@"
"$@"
単一の項目が含まれている場合にのみ正しく機能します。ご利用いただくともっといいようです-name "$1"
。複数のモードを許可するソリューションについては、以下を参照してください。
この関数は次のように書くことができます。
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for pattern do
set -- "$@" '-o' '-name' "$pattern"
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
この関数を呼び出す
DO '*.tex' '*.txt' '*.c'
実行させる
find . -type f '(' -name '*.tex' -o -name '*.txt' -o -name '*.c' ')' -exec grep -qF TODO {} ';' -print
ファイルに文字列が含まれている場合は、そのファイル名サフィックスを含むファイルのパス名のリストが生成されますTODO
。
見つかったパス名を印刷するgrep
代わりに使用するには、ビットをに変更します。これは、特に特定の式に一致するファイル名が多い場合、より効率的です。どちらの場合も使用する必要はありません。find
-exec ... -print
-exec grep -lF 'TODO' {} +
ls
ユーザーが利用できるように
DO tex txt c
あなたの機能は次のように変更されることがあります。
DO () {
# Allow for multiple patterns to be passed,
# construct the appropriate find expression from all passed patterns
for suffix do
set -- "$@" '-o' '-name' "*.$suffix" # only this line (and the previous) changed
shift
done
# There's now a -o too many at the start of "$@", remove it
shift
find . -type f '(' "$@" ')' -exec grep -qF 'TODO' {} ';' -print
}
答え2
関数に引数を引用する必要があります。それ以外の場合、シェルは引数を拡張し、関数はワイルドカードマスクの代わりにファイルのリストを取得します。
DO "*.tex"
これにより、パラメータが1つしかないため、"$1"
代わりに使用できます。"$@"