シェル内で関数を探す

シェル内で関数を探す

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

コードにはいくつかの問題があります。

  1. パターンが現在のディレクトリのファイル名と一致する場合、*.texこの関数が呼び出されるとパターンが拡張されます。この関数を呼び出すときは、DOパターンを'*.tex'"*.tex"またはで参照する必要があります。\*.tex

  2. 不要ls。すでに両方があり、find見つかったgrepファイルのパス名を報告できます。

  3. -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"代わりに使用できます。"$@"

関連情報