grep is a handy tool and I use it every day. But sometimes I wish it had some more features. For instance full-featured Perl compatible regular expressions (PCRE) since the current implementation is not complete (and I think it will never be), automatic recursive search or exclusion of non-text files etc.
Here a tool called
ack comes into play. It's a search tool and grep replacement written in Perl, which is able to do all these things. Guess what! This tool uses full-featured PCRE for searching directory trees recursively. But it does not just search all files it can get hold of but rather filters them depending on their extension and/or contents. That means it does not search shadow directories such as .svn or .git directories unless you tell it to do so. Also binary files or files with no or unknown extension are excluded by default. That means you can search VCS working copies or build directories in good conscience.
So, how does it work? Basically, there is no difference to grep in general usage. Just specify the command and the pattern (which is a PCRE not an unfunctional default grep regex, be aware of that!).
ack will now search you current directory tree for
mypattern but only include files with a known extension outside shadow directories. Which file types are known can be discovered with:
ack --help types
But of course you can also define your own types. Let's assume you are a developer working on the PHP project and you're in the team to develop PHP 6. As of the time I write this,
ack does only search PHP files with the extension
.phtml, but not
.php6. To be able to search
.php6 files we need to define this extension first:
ack --type-add php=.php6 mypattern
Now you're able to search
.php6 files as well. However, it's quite inconvenient to specify the types each time you call
ack. Therefore you can create a file called
.ackrc in your home directory. In this file you can set all parameters you want to be applied by default. In our example this file has to contain a line like this (mind the additional
When you now check the known file types with
ack --help types | ack php --nocolor
you should see the new file extension in the list.
Instead of just adding new file extensions to existing types you can of course also add completely new types or redefine existing ones. For this use
--type-set instead of
Thanks to the file type feature,
ack also allows searching for just a specific type of file. For example to search C and C++ files only, enter:
ack --type cc --type cpp searchpattern
To exclude specific file types just add a no at the beginning of the file type name.
But what if you have a directory, which includes many files without extension or with lots of extensions not known by
ack? Just use the parameter
-a. This will search all files regardless of their type but still exclude shadow directories. To include these as well, use
These are the basics, but
ack can do more. One handy feature, e.g., is to specify a pattern for a path. This enables you to select files based on a pattern instead of specifying the concrete names. You can do this by using the command
ack -G pathpattern searchpattern
Only files whose paths match the pattern
pathpattern are included in the search.
pathpattern is a PCRE which matches the whole path to the file relative to the current working directory.
Obviously, there are lots of other features and I recommend you read the man page (
man ack) but I want to show you one more feature, which makes
ack really easy to use in some cases. Have you ever struggled with searching the same set of files with different search terms? After performing the first search, you tap the up arrow key to repeat the last command and then hit the left arrow key many times to set the cursor to the position of the search pattern which is defined as the first parameter. This is very time consuming. Of course you can use the search and replace functionality of your shell history, but also that is not very convenient. What if you could specify the pattern as the last parameter? Well, with
ack you can. Just use the
ack file1 file2 file3 --match searchpattern
Now you only have to tap backspace a few times to delete the old pattern and write the new one. No need to go to the beginning of the command line anymore.
ack is not included by default in most distributions. To install it, either install the CPAN module App::Ack or use your package manager. Don't try to search your repository for ack. You'll get a lot of unrelated packages. Just install the package
ack-grep (the naming depends on your distribution).
I hope you enjoy it as much as I do. Surely, in some situations
grep is still superior (e.g. when it comes to searching a very large amount of files where performance really matters) but in most cases
ack is the way to go. I don't want to miss it anymore because it is really better than grep.