Search only in files that match a pattern with ack

Multi tool use
Can ack search only through files that match a specific 'glob' pattern (eg: search for foo in all files named "bar*.c"). The command
ack foo "bar*.c"
only works in the current directory.
Note: I know it's possible with find -exec:
find . -name "bar*.c" -type f -exec ack foo {} +
But I would like a small and simple ack command, because find doesn't skip version control directories.
ack
add a comment |
Can ack search only through files that match a specific 'glob' pattern (eg: search for foo in all files named "bar*.c"). The command
ack foo "bar*.c"
only works in the current directory.
Note: I know it's possible with find -exec:
find . -name "bar*.c" -type f -exec ack foo {} +
But I would like a small and simple ack command, because find doesn't skip version control directories.
ack
2
I don't understand, what's wrong with usingfind . -name "bar*.c" -exec ack foo {} ;
? There's nothing special aboutgrep
, you can use any command with find's-exec
.
– terdon♦
Apr 24 '14 at 11:11
1
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
2
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44
add a comment |
Can ack search only through files that match a specific 'glob' pattern (eg: search for foo in all files named "bar*.c"). The command
ack foo "bar*.c"
only works in the current directory.
Note: I know it's possible with find -exec:
find . -name "bar*.c" -type f -exec ack foo {} +
But I would like a small and simple ack command, because find doesn't skip version control directories.
ack
Can ack search only through files that match a specific 'glob' pattern (eg: search for foo in all files named "bar*.c"). The command
ack foo "bar*.c"
only works in the current directory.
Note: I know it's possible with find -exec:
find . -name "bar*.c" -type f -exec ack foo {} +
But I would like a small and simple ack command, because find doesn't skip version control directories.
ack
ack
edited Dec 19 '14 at 10:33
compie
asked Apr 24 '14 at 10:37
compiecompie
393138
393138
2
I don't understand, what's wrong with usingfind . -name "bar*.c" -exec ack foo {} ;
? There's nothing special aboutgrep
, you can use any command with find's-exec
.
– terdon♦
Apr 24 '14 at 11:11
1
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
2
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44
add a comment |
2
I don't understand, what's wrong with usingfind . -name "bar*.c" -exec ack foo {} ;
? There's nothing special aboutgrep
, you can use any command with find's-exec
.
– terdon♦
Apr 24 '14 at 11:11
1
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
2
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44
2
2
I don't understand, what's wrong with using
find . -name "bar*.c" -exec ack foo {} ;
? There's nothing special about grep
, you can use any command with find's -exec
.– terdon♦
Apr 24 '14 at 11:11
I don't understand, what's wrong with using
find . -name "bar*.c" -exec ack foo {} ;
? There's nothing special about grep
, you can use any command with find's -exec
.– terdon♦
Apr 24 '14 at 11:11
1
1
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
2
2
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44
add a comment |
9 Answers
9
active
oldest
votes
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.
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search forcpp
filesack --type=cpp <string>
. Seeack
's man page for more on all this though. But what I'm basically telling you is that you cannot search usingack
the way that you want.
– slm♦
Apr 24 '14 at 15:43
1
so it does answer in the sense that it showsack
cannot do what was asked.
– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.cfind adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file:echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
tldr;ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
add a comment |
It's easy if the file type is known, and ack knows a lot of file types. So if, for example, you want to only search in C files, than you can do:
ack --cc 'string'
But if it's not one of the known extensions, you need to define your own type. This should work:
ack --type-set barc:match:/bar.+.c/ --barc 'string'
Note that you need both --type-set and --barc.
(Thanks to Andy, who also helped with this on the mailing list.)
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.man ack
doesn't really help and doesn't havecc
when I search that.
– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
add a comment |
"What's new in ack 2?" http://beyondgrep.com/ack-2.0/
with ack 2.0, you can use the new -x to pipe filenames from one
invocation of ack into another.
ack2 -g -i filepattern | ack2 -x -w searchpattern
Only I can't get it to work:
% 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.
Thus it seems -g needs a regex, while I want a 'glob' style option...
1
Yes,-g
takes a regex, not a glob. You could write your regex as.*bar.*.c$
.
– Andy Lester
Apr 24 '14 at 15:37
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
add a comment |
Ack doesn't support glob style file selection. Since I really miss this I created a small shell script ackg:
#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +
Now you can use the command:
ackg foo "bar*.c"
But note: this will unfortunately also search in version control dirs (eg: .git).
add a comment |
Do you want only a certain pattern, or do you just want C source files?
If you want all C files, use
ack --cc foo
If you want all C files and NOT C header files use
ack --cc --no-hh foo
add a comment |
This can be done with the -G
option to ag, the silver searcher (an enhanced clone of ack-grep).
$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*.c" foo
bar_wanted.c
1:foo
Notes:
ag
uses PCRE regular expression syntax, so the regexp must bebar.*.c
instead ofbar*.c
.- The
-G
option needs to precede the search term, as anything after that is interpreted as a filename.
add a comment |
This would seem to be the fastest and safest:
find . -name '*.c' | ack -x 'some string'
-x Read the list of files to search from STDIN.
However, if the file is likely to be in your locate
database, this would be even quicker:
locate --basename '*.c' | ack -x 'some thing'
Locate can also accept old-school regular expressions, a little painful, but if you're looking for c
files, it might be required.
e.g.
locate --basename --regexp '.(c|cpp|h|hpp|cc)$' |
ack -x 'some thing'
That just translates to: "search all filename that end in c, cpp, h, hpp or cc."
add a comment |
Using zsh you can do:
ls **/a*.txt | ack --files-from=- something
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output ofls
.
– terdon♦
Apr 23 '15 at 16:36
add a comment |
@chim 's answer is the best, but its written as a comment so I'm reposting as a formal answer...
ack -g 'bbar.*.c$' | ack -x foo
I like the fact that your can regex the path...
add a comment |
Your Answer
StackExchange.ready(function() {
var channelOptions = {
tags: "".split(" "),
id: "106"
};
initTagRenderer("".split(" "), "".split(" "), channelOptions);
StackExchange.using("externalEditor", function() {
// Have to fire editor after snippets, if snippets enabled
if (StackExchange.settings.snippets.snippetsEnabled) {
StackExchange.using("snippets", function() {
createEditor();
});
}
else {
createEditor();
}
});
function createEditor() {
StackExchange.prepareEditor({
heartbeatType: 'answer',
autoActivateHeartbeat: false,
convertImagesToLinks: false,
noModals: true,
showLowRepImageUploadWarning: true,
reputationToPostImages: null,
bindNavPrevention: true,
postfix: "",
imageUploader: {
brandingHtml: "Powered by u003ca class="icon-imgur-white" href="https://imgur.com/"u003eu003c/au003e",
contentPolicyHtml: "User contributions licensed under u003ca href="https://creativecommons.org/licenses/by-sa/3.0/"u003ecc by-sa 3.0 with attribution requiredu003c/au003e u003ca href="https://stackoverflow.com/legal/content-policy"u003e(content policy)u003c/au003e",
allowUrls: true
},
onDemand: true,
discardSelector: ".discard-answer"
,immediatelyShowMarkdownHelp:true
});
}
});
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f126289%2fsearch-only-in-files-that-match-a-pattern-with-ack%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
9 Answers
9
active
oldest
votes
9 Answers
9
active
oldest
votes
active
oldest
votes
active
oldest
votes
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.
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search forcpp
filesack --type=cpp <string>
. Seeack
's man page for more on all this though. But what I'm basically telling you is that you cannot search usingack
the way that you want.
– slm♦
Apr 24 '14 at 15:43
1
so it does answer in the sense that it showsack
cannot do what was asked.
– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.cfind adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file:echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
tldr;ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
add a comment |
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.
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search forcpp
filesack --type=cpp <string>
. Seeack
's man page for more on all this though. But what I'm basically telling you is that you cannot search usingack
the way that you want.
– slm♦
Apr 24 '14 at 15:43
1
so it does answer in the sense that it showsack
cannot do what was asked.
– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.cfind adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file:echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
tldr;ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
add a comment |
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.
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.
edited Apr 24 '14 at 16:11
answered Apr 24 '14 at 12:39
slm♦slm
248k66516678
248k66516678
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search forcpp
filesack --type=cpp <string>
. Seeack
's man page for more on all this though. But what I'm basically telling you is that you cannot search usingack
the way that you want.
– slm♦
Apr 24 '14 at 15:43
1
so it does answer in the sense that it showsack
cannot do what was asked.
– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.cfind adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file:echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
tldr;ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
add a comment |
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search forcpp
filesack --type=cpp <string>
. Seeack
's man page for more on all this though. But what I'm basically telling you is that you cannot search usingack
the way that you want.
– slm♦
Apr 24 '14 at 15:43
1
so it does answer in the sense that it showsack
cannot do what was asked.
– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.cfind adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file:echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
tldr;ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
1
1
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
This doesn't answer my question (search for foo in all files named "bar*.c")
– compie
Apr 24 '14 at 14:37
1
1
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search for
cpp
files ack --type=cpp <string>
. See ack
's man page for more on all this though. But what I'm basically telling you is that you cannot search using ack
the way that you want.– slm♦
Apr 24 '14 at 15:43
@compie - it does in the sense I'm showing you how to get a slice of the files you want. To search for
cpp
files ack --type=cpp <string>
. See ack
's man page for more on all this though. But what I'm basically telling you is that you cannot search using ack
the way that you want.– slm♦
Apr 24 '14 at 15:43
1
1
so it does answer in the sense that it shows
ack
cannot do what was asked.– xealits
Aug 5 '14 at 13:49
so it does answer in the sense that it shows
ack
cannot do what was asked.– xealits
Aug 5 '14 at 13:49
@xealits - this part answers it: Searching for foo in bar*.c
find adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file: echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
@xealits - this part answers it: Searching for foo in bar*.c
find adir -iname "bar*.c" | ack --files-from=- foo
. Or, if you just want one file: echo "barBaz.c" | ack --files-from=- foo
– alexanderbird
Aug 31 '17 at 22:46
1
1
tldr;
ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
tldr;
ack -g 'bbar.*.c$' | ack -x foo
– chim
Oct 12 '17 at 14:26
add a comment |
It's easy if the file type is known, and ack knows a lot of file types. So if, for example, you want to only search in C files, than you can do:
ack --cc 'string'
But if it's not one of the known extensions, you need to define your own type. This should work:
ack --type-set barc:match:/bar.+.c/ --barc 'string'
Note that you need both --type-set and --barc.
(Thanks to Andy, who also helped with this on the mailing list.)
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.man ack
doesn't really help and doesn't havecc
when I search that.
– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
add a comment |
It's easy if the file type is known, and ack knows a lot of file types. So if, for example, you want to only search in C files, than you can do:
ack --cc 'string'
But if it's not one of the known extensions, you need to define your own type. This should work:
ack --type-set barc:match:/bar.+.c/ --barc 'string'
Note that you need both --type-set and --barc.
(Thanks to Andy, who also helped with this on the mailing list.)
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.man ack
doesn't really help and doesn't havecc
when I search that.
– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
add a comment |
It's easy if the file type is known, and ack knows a lot of file types. So if, for example, you want to only search in C files, than you can do:
ack --cc 'string'
But if it's not one of the known extensions, you need to define your own type. This should work:
ack --type-set barc:match:/bar.+.c/ --barc 'string'
Note that you need both --type-set and --barc.
(Thanks to Andy, who also helped with this on the mailing list.)
It's easy if the file type is known, and ack knows a lot of file types. So if, for example, you want to only search in C files, than you can do:
ack --cc 'string'
But if it's not one of the known extensions, you need to define your own type. This should work:
ack --type-set barc:match:/bar.+.c/ --barc 'string'
Note that you need both --type-set and --barc.
(Thanks to Andy, who also helped with this on the mailing list.)
answered Apr 24 '14 at 15:19
Amir E. AharoniAmir E. Aharoni
23113
23113
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.man ack
doesn't really help and doesn't havecc
when I search that.
– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
add a comment |
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.man ack
doesn't really help and doesn't havecc
when I search that.
– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
1
1
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Ok that works but using find and 'ack -x' is simpler. I think I will stick with that.
– compie
Apr 25 '14 at 6:58
Adding a link to the docs here would be helpful.
man ack
doesn't really help and doesn't have cc
when I search that.– YPCrumble
Apr 16 '16 at 15:19
Adding a link to the docs here would be helpful.
man ack
doesn't really help and doesn't have cc
when I search that.– YPCrumble
Apr 16 '16 at 15:19
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
ack --help=types There's everthing I can think of there. I mostly use it for Python and Ada.
– David Boshton
Feb 23 '17 at 9:58
add a comment |
"What's new in ack 2?" http://beyondgrep.com/ack-2.0/
with ack 2.0, you can use the new -x to pipe filenames from one
invocation of ack into another.
ack2 -g -i filepattern | ack2 -x -w searchpattern
Only I can't get it to work:
% 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.
Thus it seems -g needs a regex, while I want a 'glob' style option...
1
Yes,-g
takes a regex, not a glob. You could write your regex as.*bar.*.c$
.
– Andy Lester
Apr 24 '14 at 15:37
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
add a comment |
"What's new in ack 2?" http://beyondgrep.com/ack-2.0/
with ack 2.0, you can use the new -x to pipe filenames from one
invocation of ack into another.
ack2 -g -i filepattern | ack2 -x -w searchpattern
Only I can't get it to work:
% 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.
Thus it seems -g needs a regex, while I want a 'glob' style option...
1
Yes,-g
takes a regex, not a glob. You could write your regex as.*bar.*.c$
.
– Andy Lester
Apr 24 '14 at 15:37
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
add a comment |
"What's new in ack 2?" http://beyondgrep.com/ack-2.0/
with ack 2.0, you can use the new -x to pipe filenames from one
invocation of ack into another.
ack2 -g -i filepattern | ack2 -x -w searchpattern
Only I can't get it to work:
% 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.
Thus it seems -g needs a regex, while I want a 'glob' style option...
"What's new in ack 2?" http://beyondgrep.com/ack-2.0/
with ack 2.0, you can use the new -x to pipe filenames from one
invocation of ack into another.
ack2 -g -i filepattern | ack2 -x -w searchpattern
Only I can't get it to work:
% 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.
Thus it seems -g needs a regex, while I want a 'glob' style option...
answered Apr 24 '14 at 14:29
compiecompie
393138
393138
1
Yes,-g
takes a regex, not a glob. You could write your regex as.*bar.*.c$
.
– Andy Lester
Apr 24 '14 at 15:37
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
add a comment |
1
Yes,-g
takes a regex, not a glob. You could write your regex as.*bar.*.c$
.
– Andy Lester
Apr 24 '14 at 15:37
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
1
1
Yes,
-g
takes a regex, not a glob. You could write your regex as .*bar.*.c$
.– Andy Lester
Apr 24 '14 at 15:37
Yes,
-g
takes a regex, not a glob. You could write your regex as .*bar.*.c$
.– Andy Lester
Apr 24 '14 at 15:37
2
2
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
@AndyLester Thanks for confirming. Do you like the idea of a 'glob' option for ack?
– compie
Apr 25 '14 at 6:59
add a comment |
Ack doesn't support glob style file selection. Since I really miss this I created a small shell script ackg:
#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +
Now you can use the command:
ackg foo "bar*.c"
But note: this will unfortunately also search in version control dirs (eg: .git).
add a comment |
Ack doesn't support glob style file selection. Since I really miss this I created a small shell script ackg:
#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +
Now you can use the command:
ackg foo "bar*.c"
But note: this will unfortunately also search in version control dirs (eg: .git).
add a comment |
Ack doesn't support glob style file selection. Since I really miss this I created a small shell script ackg:
#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +
Now you can use the command:
ackg foo "bar*.c"
But note: this will unfortunately also search in version control dirs (eg: .git).
Ack doesn't support glob style file selection. Since I really miss this I created a small shell script ackg:
#!/bin/sh
# 'glob' support for ack
find -name "$2" -type f -exec ack "$1" {} +
Now you can use the command:
ackg foo "bar*.c"
But note: this will unfortunately also search in version control dirs (eg: .git).
edited Jul 30 '15 at 8:45
answered Dec 19 '14 at 10:37
compiecompie
393138
393138
add a comment |
add a comment |
Do you want only a certain pattern, or do you just want C source files?
If you want all C files, use
ack --cc foo
If you want all C files and NOT C header files use
ack --cc --no-hh foo
add a comment |
Do you want only a certain pattern, or do you just want C source files?
If you want all C files, use
ack --cc foo
If you want all C files and NOT C header files use
ack --cc --no-hh foo
add a comment |
Do you want only a certain pattern, or do you just want C source files?
If you want all C files, use
ack --cc foo
If you want all C files and NOT C header files use
ack --cc --no-hh foo
Do you want only a certain pattern, or do you just want C source files?
If you want all C files, use
ack --cc foo
If you want all C files and NOT C header files use
ack --cc --no-hh foo
answered Apr 24 '14 at 14:36
Andy LesterAndy Lester
423415
423415
add a comment |
add a comment |
This can be done with the -G
option to ag, the silver searcher (an enhanced clone of ack-grep).
$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*.c" foo
bar_wanted.c
1:foo
Notes:
ag
uses PCRE regular expression syntax, so the regexp must bebar.*.c
instead ofbar*.c
.- The
-G
option needs to precede the search term, as anything after that is interpreted as a filename.
add a comment |
This can be done with the -G
option to ag, the silver searcher (an enhanced clone of ack-grep).
$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*.c" foo
bar_wanted.c
1:foo
Notes:
ag
uses PCRE regular expression syntax, so the regexp must bebar.*.c
instead ofbar*.c
.- The
-G
option needs to precede the search term, as anything after that is interpreted as a filename.
add a comment |
This can be done with the -G
option to ag, the silver searcher (an enhanced clone of ack-grep).
$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*.c" foo
bar_wanted.c
1:foo
Notes:
ag
uses PCRE regular expression syntax, so the regexp must bebar.*.c
instead ofbar*.c
.- The
-G
option needs to precede the search term, as anything after that is interpreted as a filename.
This can be done with the -G
option to ag, the silver searcher (an enhanced clone of ack-grep).
$ echo foo > bar_wanted.c
$ echo foo > unwanted.c
$ ag -G "bar.*.c" foo
bar_wanted.c
1:foo
Notes:
ag
uses PCRE regular expression syntax, so the regexp must bebar.*.c
instead ofbar*.c
.- The
-G
option needs to precede the search term, as anything after that is interpreted as a filename.
edited May 23 '17 at 12:40
Community♦
1
1
answered Aug 5 '15 at 6:27
Jon Olav VikJon Olav Vik
1113
1113
add a comment |
add a comment |
This would seem to be the fastest and safest:
find . -name '*.c' | ack -x 'some string'
-x Read the list of files to search from STDIN.
However, if the file is likely to be in your locate
database, this would be even quicker:
locate --basename '*.c' | ack -x 'some thing'
Locate can also accept old-school regular expressions, a little painful, but if you're looking for c
files, it might be required.
e.g.
locate --basename --regexp '.(c|cpp|h|hpp|cc)$' |
ack -x 'some thing'
That just translates to: "search all filename that end in c, cpp, h, hpp or cc."
add a comment |
This would seem to be the fastest and safest:
find . -name '*.c' | ack -x 'some string'
-x Read the list of files to search from STDIN.
However, if the file is likely to be in your locate
database, this would be even quicker:
locate --basename '*.c' | ack -x 'some thing'
Locate can also accept old-school regular expressions, a little painful, but if you're looking for c
files, it might be required.
e.g.
locate --basename --regexp '.(c|cpp|h|hpp|cc)$' |
ack -x 'some thing'
That just translates to: "search all filename that end in c, cpp, h, hpp or cc."
add a comment |
This would seem to be the fastest and safest:
find . -name '*.c' | ack -x 'some string'
-x Read the list of files to search from STDIN.
However, if the file is likely to be in your locate
database, this would be even quicker:
locate --basename '*.c' | ack -x 'some thing'
Locate can also accept old-school regular expressions, a little painful, but if you're looking for c
files, it might be required.
e.g.
locate --basename --regexp '.(c|cpp|h|hpp|cc)$' |
ack -x 'some thing'
That just translates to: "search all filename that end in c, cpp, h, hpp or cc."
This would seem to be the fastest and safest:
find . -name '*.c' | ack -x 'some string'
-x Read the list of files to search from STDIN.
However, if the file is likely to be in your locate
database, this would be even quicker:
locate --basename '*.c' | ack -x 'some thing'
Locate can also accept old-school regular expressions, a little painful, but if you're looking for c
files, it might be required.
e.g.
locate --basename --regexp '.(c|cpp|h|hpp|cc)$' |
ack -x 'some thing'
That just translates to: "search all filename that end in c, cpp, h, hpp or cc."
answered Oct 6 '16 at 11:00
OrwellophileOrwellophile
27933
27933
add a comment |
add a comment |
Using zsh you can do:
ls **/a*.txt | ack --files-from=- something
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output ofls
.
– terdon♦
Apr 23 '15 at 16:36
add a comment |
Using zsh you can do:
ls **/a*.txt | ack --files-from=- something
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output ofls
.
– terdon♦
Apr 23 '15 at 16:36
add a comment |
Using zsh you can do:
ls **/a*.txt | ack --files-from=- something
Using zsh you can do:
ls **/a*.txt | ack --files-from=- something
answered Apr 23 '15 at 16:16
user1622150user1622150
11
11
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output ofls
.
– terdon♦
Apr 23 '15 at 16:36
add a comment |
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output ofls
.
– terdon♦
Apr 23 '15 at 16:36
2
2
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output of
ls
.– terdon♦
Apr 23 '15 at 16:36
Note that this will break if your file names contain spaces. It is very rarely a good idea to parse the output of
ls
.– terdon♦
Apr 23 '15 at 16:36
add a comment |
@chim 's answer is the best, but its written as a comment so I'm reposting as a formal answer...
ack -g 'bbar.*.c$' | ack -x foo
I like the fact that your can regex the path...
add a comment |
@chim 's answer is the best, but its written as a comment so I'm reposting as a formal answer...
ack -g 'bbar.*.c$' | ack -x foo
I like the fact that your can regex the path...
add a comment |
@chim 's answer is the best, but its written as a comment so I'm reposting as a formal answer...
ack -g 'bbar.*.c$' | ack -x foo
I like the fact that your can regex the path...
@chim 's answer is the best, but its written as a comment so I'm reposting as a formal answer...
ack -g 'bbar.*.c$' | ack -x foo
I like the fact that your can regex the path...
edited Jan 10 at 19:04
answered Jan 10 at 18:28
arodarod
23124
23124
add a comment |
add a comment |
Thanks for contributing an answer to Unix & Linux Stack Exchange!
- Please be sure to answer the question. Provide details and share your research!
But avoid …
- Asking for help, clarification, or responding to other answers.
- Making statements based on opinion; back them up with references or personal experience.
To learn more, see our tips on writing great answers.
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
StackExchange.ready(
function () {
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f126289%2fsearch-only-in-files-that-match-a-pattern-with-ack%23new-answer', 'question_page');
}
);
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Sign up or log in
StackExchange.ready(function () {
StackExchange.helpers.onClickDraftSave('#login-link');
});
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
Required, but never shown
3PFCAp0P7XN
2
I don't understand, what's wrong with using
find . -name "bar*.c" -exec ack foo {} ;
? There's nothing special aboutgrep
, you can use any command with find's-exec
.– terdon♦
Apr 24 '14 at 11:11
1
@terdon find also searches through version control directories and I don't want that.
– compie
Apr 24 '14 at 13:41
2
Then please edit your question and explain the limitations you need to work around.
– terdon♦
Apr 24 '14 at 13:44