The “find” command is one of the most powerful and useful Unix commands, you can use it to locate files, and then perform some type of action on the files after they’ve been located. With this capability, you can locate files using powerful search criteria, and then run any Unix command you want on the files you locate.
Find Strings
In the following example I’ll recursively search a directory for files containing the ‘test’ string and output the name of the files and the line number:
$ grep -in -e 'test' `find -type f`
This command will search in the current directory and all sub directories. All files containing the string ‘test’ will have their path printed to standard output:
./build/build.properties:4:project.name=test ./build/build.xml:12:<target name="sync:test">
Count Strings
If you only want to count the matching lines for each file, then you can use the following command:
$ grep -inc -e 'test' `find -type f` | grep -v :0
This will output:
./build/build.properties:1 ./build/build.xml:2
Replace Strings
And finally, if you want to replace all occurrences of the search string with the replacement string:
$ sed -i 's/search/replace/' `find -type f`
Linux Commands
Learn more about these commands:
4 responses to “The easiest way to search and replace in files”
I’d call sed the linux power users’ search and replace tool. A simpler (read: less likely to lead to frustration and/or tears) recursive replace command for linux would be “rpl”.
Running find inside backticks is a recipe for trouble – it can easily overflow the space allowed for a command’s arguments. It will also fail when filenames have spaces.
This is better:
find . -type f -print0 | xargs -0 sed -i ‘s/search/replace/’
I often put the . after find so I know the command will work on BSD/OSX. -print0 will output the files separated by a NUL character so spaces in filenames aren’t ambiguous. xargs will take a stream and split it into pieces small enough to fit in the command buffer. -0 tells xargs to expect a NUL delimited stream. xargs will run sed as few times as possible, better than using -exec in find.
I hope this helps someone.
…and if I’m doing anything more subtle/conditional/complex than that, I break out Perl (man File::Find).
Hi Andrew, thanks for the tip! Very useful. As a matter of fact, I’m doing something similar to count the matching lines for each file:
find . -type f -print0 | xargs -0 grep -c “keyword” | grep -v :0
I’ll add this info to the post. Thanks :)