Grep's out of date? Full ACK!
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 mypattern
That's it! 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 .php
, .phpt
, .php3
, .php4
, .php5
and .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 =
!):
--type-add=php=.php6
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 --type-add
.
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 -u
.
More features!
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 -G pattern
.
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 --match
command.
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.
Install ack
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
or ack-grep
(the naming depends on your distribution).
To get more information about this handy tool, read the man page or visit the developers' website on betterthangrep.com.
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.