只能通过匹配特定“glob”模式的文件进行确认搜索(例如:在所有名为“bar*.c”的文件中搜索 foo)。命令
ack foo "bar*.c"
Run Code Online (Sandbox Code Playgroud)
仅适用于当前目录。
注意:我知道 find -exec 是可能的:
find . -name "bar*.c" -type f -exec ack foo {} +
Run Code Online (Sandbox Code Playgroud)
但我想要一个小而简单的 ack 命令,因为 find 不会跳过版本控制目录。
slm*_*slm 32
根据手册页中显示的概要,我会说是的,它可以处理目录,但是查看开关,它不能仅查找基于模式的文件。为此,您必须入伍find。该命令ack确实包含该选项--files-from=FILE,因此可以从find.
概要
ack [options] PATTERN [FILE...]
ack -f [options] [DIRECTORY...]
Run Code Online (Sandbox Code Playgroud)
用法
--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.
Run Code Online (Sandbox Code Playgroud)
有一个--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".
Run Code Online (Sandbox Code Playgroud)
我能想到的唯一另一种方法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.
Run Code Online (Sandbox Code Playgroud)
要查看可用的类型:
$ ack --help-types | grep -E "perl|cpp"
Run Code Online (Sandbox Code Playgroud)
格式。例如, --type=perl 和 --perl 都可以工作。--[no]cpp .cpp .cc .cxx .m .hpp .hh .h .hxx --[no]objcpp .mm .h --[no]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
Run Code Online (Sandbox Code Playgroud)
查找所有 C++ 文件:
$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h
Run Code Online (Sandbox Code Playgroud)
那么你怎么能完成你想要的呢?好吧,您可能必须使用以下方法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
Run Code Online (Sandbox Code Playgroud)
您还可以使用ack的功能来搜索与文件名中的给定模式匹配的文件(使用-g <pattern>),然后将此列表传递给ackusing-x或--files-from=-..
使用-x:
$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo
dir1/bar1.c
1:foo
2:foo
Run Code Online (Sandbox Code Playgroud)
使用-files-from=-:
$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo
dir1/bar1.c
1:foo
2:foo
Run Code Online (Sandbox Code Playgroud)
在任何一种情况下,我们都会使用此正则表达式匹配您想要的文件名:
\bbar.*.c$
Run Code Online (Sandbox Code Playgroud)
这匹配名称为bar.*c并且在.c使用行尾锚点之后结束的文件$。我们还希望确保名称具有使用\b. 对于包含边界字符(例如$bar.c或 )的文件,这将失败%bar.c。
小智 14
如果知道文件类型就很容易了,ack 知道很多文件类型。因此,例如,如果您只想在 C 文件中搜索,那么您可以这样做:
ack --cc 'string'
Run Code Online (Sandbox Code Playgroud)
但如果它不是已知的扩展之一,则需要定义自己的类型。这应该有效:
ack --type-set barc:match:/bar.+\.c/ --barc 'string'
Run Code Online (Sandbox Code Playgroud)
请注意,您需要 --type-set 和 --barc。
(感谢 Andy,他也在邮件列表中帮助解决了这个问题。)
“ack 2 有什么新东西?” http://beyondgrep.com/ack-2.0/
使用 ack 2.0,您可以使用新的 -x 将文件名从一个 ack 调用传递到另一个调用。
ack2 -g -i filepattern | ack2 -x -w searchpattern
Run Code Online (Sandbox Code Playgroud)
只有我无法让它工作:
% ack -g "*bar*.c"
Invalid regex '*bar*.c':
Quantifier follows nothing in regex; marked by <-- HERE in m/* <-- HERE bar*.c/ at ack line 314.
Run Code Online (Sandbox Code Playgroud)
因此似乎 -g 需要一个正则表达式,而我想要一个“glob”风格的选项......
小智 7
这似乎是最快和最安全的:
find . -name '*.c' | ack -x 'some string'
Run Code Online (Sandbox Code Playgroud)
-x 从 STDIN 读取要搜索的文件列表。
但是,如果该文件可能在您的locate数据库中,这会更快:
locate --basename '*.c' | ack -x 'some thing'
Run Code Online (Sandbox Code Playgroud)
Locate 也可以接受老式的正则表达式,有点痛苦,但如果你正在寻找c文件,它可能是必需的。
例如
locate --basename --regexp '\.\(c\|cpp\|h\|hpp\|cc\)$' |
ack -x 'some thing'
Run Code Online (Sandbox Code Playgroud)
这只是转换为:“搜索所有以 c、cpp、h、hpp 或 cc 结尾的文件名。”