Tuesday, February 3, 2009

New Favorite Find/Replace (bash) shell commands

These commands took a while for me to find and I now use them very, very often. One is to find files in all subdirectories excluding certain directories (in this case, the subversion ".svn" directories). The second expression replaces regular expressions in all the files that match the find in the first expression:

# To grep for things excluding subversion .svn directories

find . -path '*/.svn' -prune -o -type f -print | xargs -e fgrep -I PATTERN

# To replace the same (using sed), only in files that grep matched, only in non .svn files.
find . -path '*/.svn' -prune -o -type f -print | xargs -e fgrep -l -I 'OLD' | xargs sed -i -e 's/OLD/NEW/g'


UPDATE 2009-02-09
I was browsing at Barnes and Noble over the weekend and the O'Reilly Pocket Guide to Grep mentioned an --exclude-dir option. I looked at the man page again and it's there too. I even googled again and found it right away. How did I miss it? That makes things much easier.

# To grep for things excluding subversion .svn directories

fgrep --exclude-dir='.svn' -rI PATTERN *

# To replace the same (using sed), only in files that grep matched, only in non .svn files.
fgrep --exclude-dir='.svn' -rIl 'OLD' * | xargs sed -i -e 's/OLD/NEW/g'


UPDATE 2010-03-31
# To find whole words, using an even briefer syntax for

# chaining the output of grep into the input for sed.
# Taken from a shell script that sets oldWord and
# newWord, but you get the idea:
sed -i -e "s/\<$oldWord\>/$newWord/g" $(fgrep --exclude-dir='.svn' -wrIl "$oldWord" *)