只能确认通过匹配特定“ glob”模式的文件进行搜索(例如:在名为“ bar * .c”的所有文件中搜索foo)。命令
ack foo "bar*.c"
仅适用于当前目录。
注意:我知道使用find -exec是可能的:
find . -name "bar*.c" -type f -exec ack foo {} +
但是我想要一个简单的ack命令,因为find不会跳过版本控制目录。
只能确认通过匹配特定“ glob”模式的文件进行搜索(例如:在名为“ bar * .c”的所有文件中搜索foo)。命令
ack foo "bar*.c"
仅适用于当前目录。
注意:我知道使用find -exec是可能的:
find . -name "bar*.c" -type f -exec ack foo {} +
但是我想要一个简单的ack命令,因为find不会跳过版本控制目录。
Answers:
基于手册页中显示的概要,我会说是的,它可以处理目录,但是从开关的角度来看,它不能仅基于模式来查找文件。为此,您必须征募find
。该命令ack
确实包含该选项,--files-from=FILE
以便可以从中获取文件列表find
。
概要
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都可以工作。-[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
查找所有C ++文件:
$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h
那么,您如何才能完成自己想要的?好吧,您将不得不使用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>
),然后将此列表传递给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
例如。
cpp
文件ack --type=cpp <string>
。有关ack
所有这些的更多信息,请参见的手册页。但是,我基本上要告诉您的是,您无法使用ack
所需的方式进行搜索。
ack
无法完成所要求的事情。
find adir -iname "bar*.c" | ack --files-from=- foo
。或者,如果您只想要一个文件:echo "barBaz.c" | ack --files-from=- foo
ack -g '\bbar.*.c$' | ack -x foo
如果文件类型已知,而ack知道很多文件类型,则很容易。因此,例如,如果您只想搜索C文件,则可以执行以下操作:
ack --cc 'string'
但是,如果它不是已知的扩展之一,则需要定义自己的类型。这应该工作:
ack --type-set barc:match:/bar.+\.c/ --barc 'string'
请注意,您同时需要--type-set和--barc。
(感谢Andy,他也在邮件列表中提供了帮助。)
man ack
搜索并没有真正的帮助,也没有帮助cc
。
“ ack 2中有什么新功能?” http://beyondgrep.com/ack-2.0/
在ack 2.0中,您可以使用新的-x将ack的一次调用中的文件名传递到另一调用中。
ack2 -g -i filepattern | ack2 -x -w searchpattern
只有我不能使它工作:
% 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.
因此-g似乎需要一个正则表达式,而我想要一个'glob'样式选项...
-g
需要一个正则表达式,而不是全局对象。您可以将正则表达式写为.*bar.*\.c$
。
这似乎是最快和最安全的:
find . -name '*.c' | ack -x 'some string'
-x 读取文件列表以从STDIN中搜索。
但是,如果文件可能位于locate
数据库中,则速度会更快:
locate --basename '*.c' | ack -x 'some thing'
Locate还可以接受老式的正则表达式,这有点麻烦,但是如果您要查找c
文件,则可能需要使用。
例如
locate --basename --regexp '\.\(c\|cpp\|h\|hpp\|cc\)$' |
ack -x 'some thing'
只是翻译为:“搜索以c,cpp,h,hpp或cc结尾的所有文件名。”
您是否只需要某种模式,还是只需要C源文件?
如果要所有C文件,请使用
ack --cc foo
如果要使用所有C文件而不是C头文件
ack --cc --no-hh foo
使用zsh,您可以执行以下操作:
ls **/a*.txt | ack --files-from=- something
ls
。
find . -name "bar*.c" -exec ack foo {} \;
?没什么特别的grep
,您可以将任何命令与find一起使用-exec
。