ack-grep - a source-aware grep replacement (searching for content in files)
ack (or ack-grep) is a nice "grep" replacement, when searching in a directory with source files.
It does not require any path to start searching and the recursive option is enabled by default. Also, it will exclude directories of version control systems (like .svn, CVS, .bzr, .git) and nicely formats hits.
E.g., "ack-grep foo" will search all (relevant) files in the current directory for "foo". And if the current directory is under source control, it will be much faster than using "grep -R foo .", since it excludes the control directories. (Ye
I haven't tinkered with its options or man page, although I'm using it since quite some time now, since the defaults are so good already and it provides a great out-of-box experience and performance boost.
The man page states when to use the "normal" grep:
WHEN TO USE GREP
ack-grep trumps grep as an everyday tool 99% of the time, but don’t throw grep away, because there are times you’ll still need it.
E.g., searching through huge files looking for regexes that can be expressed with grep syntax should be quicker with grep.
Additionally, "grep" appears to be still more useful when chaining commands, e.g. to find all references of "css" in the file list of "ack-grep" ("dpkg -L ack-grep | xargs grep css"). When using ack-grep here, it will also recursively search in all listed directories (as in "for i in $(dpkg -L ack-grep); do test -d $i && echo $i; done").
On Debian/Ubuntu, ack-grep is only a "sudo apt-get install ack-grep" away..
(The ack homepage has some convincing Testimonials, too)
My favorite feature is searching in specific file types: grin -I*.js connect. I know ack can do this, but I could never remember the --type flags for it. The other cool thing is that the output of grin is colored and highlights where in the line the pattern shows up.
grep will also recurse into directories ('-r'), and it will highlight hits ('--color'). It will skip source control directories ('--exclude-dir=\.git')
ack is advertised to be faster, but it is only faster because it skips searching a bunch of files. If you configure grep to skip source control, as above, and skip binary files ('-I'), then ack is actually slower than grep.
It's true that grep needs configuring to make it behave the way you want. So instead of installing 'ack', create an executable on your path to select the default options you want grep to use. Mine looks like:
$ cat `which grp`
grep -rI --color --exclude-dir=\.bzr --exclude-dir=\.git --exclude-dir=\.hg --exclude-dir=\.svn --exclude-dir=build --exclude-dir=dist --exclude=tags $*
I did this once in the 1980s, and grep has been fine for me ever since.
The whole 'ack' project is a massive waste of time - throwing away decades of bugfixes, optimisations, and a community of knowledge, for no reason at all.
The premise of "for no reason at all" is also untrue. You may not agree with the reasons, but the reasons do indeed exist.
Nobody says that grep can't recurse or colorize or skip directories. The difference is that ack does those things out of the box without having to customize it. For old Unix hands like us, that's not a problem. For others, it is.
ack-grep is a waste of time compared to the imaginary alternative of having written such a mere lightweight easy-to-maintain grep wrapper which would have benefited the same users the same amount of time.
As to speed, for me, this
find . -name "*.[ch]*" ! -regex ".*[/]\..+[/]?.*" -print0 | xargs -0 -n1000 grep -IHn something
seems to often run faster than
ack-grep --cpp something
when searching in cpp files.
Same for dropping --cpp and -name "*.[ch]*". This on Ubuntu Lucid on a Core i7, measured using GNU time.
That command can be aliased, or wrapped by a small script in any scripting language to provide the ack options for language specific file extentions, without reinventing the wheel. (Note for me it often runs much faster when run twice, even with different keywords some caching going on somewhere, which is lost on ack).
As alias (put into your ~/.alias in Linux):
alias ag='find . ! -regex ".*[/]\..+[/]?.*" -print0 | xargs -0 -n1000 grep -IHn'
Also the command example I give does not hide unusual extentions that the user did not know were excluded from ack.
Also note the rather new parallel command for such optimisation on multi-cores: http://www.gnu.org/software/parallel/man.html#example__parallel_grep which can make the find / parallel/ grep combo much faster than ack (xargs does not do well for parallel output, see http://www.gnu.org/software/parallel/man.html#differences_between_xargs_and_gnu_parallel)