ackパターンに一致するファイルからのみ検索

ackパターンに一致するファイルからのみ検索

検証検索は、特定の「glob」パターンと一致するファイルによってのみ実行できます(たとえば、「bar * .c」という名前のすべてのファイルでfooを検索するなど)。注文する

ack foo "bar*.c"

現在のディレクトリにのみ適用されます。

注:find -execを使用すると可能であることがわかります。

find . -name "bar*.c" -type f -exec ack foo {} + 

しかし、findはバージョン管理ディレクトリをスキップしないので、小さくてシンプルなackコマンドが必要です。

答え1

カタログ検索

マニュアルページに表示される概要によると、「はい」と言いたいと思います。ディレクトリを処理できますが、スイッチを見るとパターンに基づいてファイルを見つけることはできません。そのためには軍隊に入隊しなければなりませんfind。コマンドにはからダウンロードできるackオプションが含まれています。--files-from=FILEfind

要約

       ack [options] PATTERN [FILE...]
       ack -f [options] [DIRECTORY...]

使用法

   --files-from=FILE
       The list of files to be searched is specified in FILE.  The list of
       files are separated by newlines.  If FILE is "-", the list is
       loaded from standard input.

--ignore-file=欲しいものを提供するオプションがありますが、実際に使用するのは少し痛いようです。

   --ignore-file=FILTERTYPE:FILTERARGS
       Ignore files matching FILTERTYPE:FILTERARGS.  The filters are
       specified identically to file type filters as seen in "Defining
       your own types".

特定の種類のファイル検索

私が考えることができる唯一の他の方法は、ackスイッチを使用することです--type

   --type=[no]TYPE
       Specify the types of files to include or exclude from a search.
       TYPE is a filetype, like perl or xml.  --type=perl can also be
       specified as --perl, and --type=noperl can be done as --noperl.

       If a file is of both type "foo" and "bar", specifying --foo and
       --nobar will exclude the file, because an exclusion takes
       precedence over an inclusion.

利用可能な種類を確認するには、次の手順を実行します。

$ ack --help-types | grep -E "perl|cpp"

滞在。たとえば、--type=perl と --perl の両方が有効です。 --[いいえ]cpp .cpp .cc .cxx .m .hpp .hh .h .hxx --[いいえ]objcpp .mm .h --[いいえ]perl .pl .pm .pod .t .psgi;行は /^#!.*\bperl/ --[no]perltest .t と一致します。

はい

ファイル名(*.pm、*.pl、*.t、および*.pod)とshebang行に基づいてすべてのPerlファイルを見つけます。

$ ack -f --type perl 
examples/iwatch/iwatch/iwatch
examples/nytprof_perl/bad.pl

すべてのC ++ファイルを探す:

$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h

bar*.cでfooを検索してください。

それでは、あなたが望むことをどのように達成できますか?findこれを行うには、次の方法を使用する必要があります。

$ find adir -iname "bar*.c" | ack --files-from=- foo
adir/bar1.c
1:foo
2:foo

adir/dir1/bar1.c
1:foo
2:foo

ack関数を使用して、ファイル名から指定されたパターンと一致するファイルを検索し、(使用)または..を使用して-g <pattern>このリストを2番目の呼び出しに渡すこともできます。ack-x--files-from=-

使用-x:

$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

使用-files-from=-:

$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo

dir1/bar1.c
1:foo
2:foo

どちらの場合も、次の正規表現を使用して目的のファイル名と一致させます。

\bbar.*.c$

bar.*cこれは行末アンカーと命名され、終了するファイルと一致します。また、名前に境界文字が使用されていることを確認したいと思います。たとえば、または同じ境界文字を含むファイルの場合は失敗します。.c$\b$bar.c%bar.c

答え2

ファイルの種類を知っていると簡単で、ackは多くのファイルの種類について知っています。たとえば、Cファイルからのみ検索したい場合は、次のことができます。

ack --cc 'string'

ただし、既知の拡張機能の1つではない場合は、一意の型を定義する必要があります。これは働きます:

ack --type-set barc:match:/bar.+\.c/ --barc 'string'

--type-set と --barc が必要です。

(メーリングリストにも協力してくれたAndyに感謝します。)

答え3

これが最も速く安全なようです。

find . -name '*.c' | ack -x 'some string'

- X STDINで検索するファイルのリストを読みます。

ただし、ファイルがデータベースにある場合は、locateより高速です。

locate --basename '*.c' | ack -x 'some thing'

Locate は古い正規表現も受け入れますが、これは少し面倒ですが、ファイルを探している場合はc必要な場合があります。 例えば

locate --basename --regex '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    ack -x 'some thing'

これは単に次のように解釈されます。 "c、cpp、h、hpp、またはccで終わるすべてのファイル名を検索します。"

@nyxeeの非常に良い質問について私が見ることができる唯一の答えは、別のパイプを追加することです。

locate --basename --regex '\.\(c\|cpp\|h\|hpp\|cc\)$' |
    grep -v '/\.'                                     |
    ack -x 'some thing'

これにより、次から始まるディレクトリまたはサブディレクトリをスキップします。.

答え4

@ chimさんの答えが一番いいのにコメントで書いたので正式な答えに戻します...

ack -g '\bbar.*.c$' | ack -x foo

正規表現パスを使用できるという事実が気に入っています...

関連情報