Searching directories
Based on the synopsis shown in the man page I would say yes it can process a directory, but looking at the switches it cannot look for just a file based on a pattern. For that you'll have to enlist find
. The command ack
does include the option --files-from=FILE
so that it can be fed a list of files from find
.
synopsis
ack [options] PATTERN [FILE...]
ack -f [options] [DIRECTORY...]
usage
--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.
There is the --ignore-file=
option which may give you what you want but seems a bit of a pain to actually use.
--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".
Searching specific types of files
The only other way I can conceive of doing just this via ack
is to use its --type
switch:
--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.
To see what types are available:
$ ack --help-types | grep -E "perl|cpp"
format. For example, both --type=perl and --perl work.
--[no]cpp .cpp .cc .cxx .m .hpp .hh .h .hxx
--[no]objcpp .mm .h
--[no]perl .pl .pm .pod .t .psgi; first line matches /^#!.*\bperl/
--[no]perltest .t
Examples
Find all the Perl files, based on both the filename (*.pm, *.pl, *.t and *.pod) and the shebang line.
$ ack -f --type perl
examples/iwatch/iwatch/iwatch
examples/nytprof_perl/bad.pl
Find all the C++ files:
$ ack -f --type=cpp
Shared/Scanner.h
Shared/Sorter.h
Shared/DicomHelper.cpp
Shared/DicomDeviationWriter.h
Searching for foo in bar*.c
So then how can you accomplish what you want? Well you'll have to likely use find
to do this:
$ find adir -iname "bar*.c" | ack --files-from=- foo
adir/bar1.c
1:foo
2:foo
adir/dir1/bar1.c
1:foo
2:foo
You can also use ack
's ability to search for files that match a given pattern in their filenames (using -g <pattern>
), and then pass this list to a second invocation of ack
using -x
or --files-from=-
..
Using -x
:
$ ack -g '\bbar.*.c$' | ack -x foo
bar1.c
1:foo
2:foo
dir1/bar1.c
1:foo
2:foo
Using -files-from=-
:
$ ack -g '\bbar.*.c$' | ack --files-from=- foo
bar1.c
1:foo
2:foo
dir1/bar1.c
1:foo
2:foo
In either case we're matching the filenames that you want using this regex:
\bbar.*.c$
This matches files whose name is bar.*c
and end after the .c
using the end of line anchor, $
. We also look to make sure that the names have a boundary character using \b
. This will fail for files that contain boundary characters such as $bar.c
or %bar.c
for example.
find . -name "bar*.c" -exec ack foo {} \;
? There's nothing special aboutgrep
, you can use any command with find's-exec
.