I'm trying to search for files that contain 2 patterns. I'm guessing piping is the way to go but I'm doing something wrong, because the following doesn't work:
ack -l "pattern1" | ack -l "pattern2"
What am I missing?
I'm trying to search for files that contain 2 patterns. I'm guessing piping is the way to go but I'm doing something wrong, because the following doesn't work:
ack -l "pattern1" | ack -l "pattern2"
What am I missing?
I take it from your question that you want files that contains pattern1 and also contain pattern2, even if they are on different lines.
Here's one way to do it:
ack -l pattern2 $(ack -l pattern1)
Here's another:
ack -l pattern1 | ack -l -x pattern2
The -x
says "Get the list of files to search from standard input, as if I were the xargs
program." (This is assuming you're using ack 2.x or higher)
Update: If the intent is to find both patterns anywhere in the file (not necessarily on the same line), Andy Lester's answer offers simple solutions.
-l
outputs the filename rather than the matching line(s), so do not use -l
in your first ack
invocation (or else the second one will only receive the filename as its input).
However, as @Mr. Llama correctly points out, even that wouldn't work, because the 2nd ack
would print -
(stdin) in the event of a match, given that its input comes from a pipe rather than a file.
ack "pattern1" | ack -l "pattern2" # !! prints '-' in case of match
Generally, -l
only makes sense with filenames as operands.
Aside from that, however, your command would only match if (at least one) single line contained both search terms.
If that is truly the intent, you could get away with a single invocation of ack
, using regex alternation (the parentheses are used for visual clarity and aren't strictly necessary):
ack -l "(pattern1).*(pattern2)|(pattern2).*(pattern1)" file