Unix/Linux Find & Replace in Multiple Files
February 1, 2008 – 11:00 pm by gabeHere’s a classic that I originally published 20 February 2003 - 11:14. This entry was the #1 most popular post between 11/19/2005 and 11/13/2006, receiving 16,443 page views (13,653 unique) during that time.
Since it’s damn near impossible to find online the simplest way to scan a Unix directory of files, search for one text pattern, and replace with another, I am now archiving the simplest method I could find (which I’ve tested and have proven that it works beautifully). Simply cd to the directory where your files live, modify (or leave) the *.php to match the file type you are modifying, then run the following at the command line:
-
for fl in *.php; do
mv $fl $fl.old
sed ’s/FINDSTRING/REPLACESTRING/g’ $fl.old > $fl
#rm -f $fl.old
done
Uncomment rm -f $fl.old if you don’t want to bother keeping a copy of the old files. Simple, eh? It’s all about sed, baby.
Linux: Replace a string in several text files
[ Subscribe to gabeanderson.com via email or RSS feed. ]
Hi, I'm Gabe Anderson. I've published more than 2,000 personal and professional blog entries on my other blogs since 2000.
24 Responses to “Unix/Linux Find & Replace in Multiple Files”
Awesome little script; thanks for sharing.
By Indrid Cold on Apr 25, 2003
Thanks a lot for this. I’ve been looking for a way to do this for quite a while. I’m suprised its not a function of sed or a built in linux command.
Now if only you can make this recursive through subdirectories!
By Matt Toledo on Jun 10, 2003
The following script includes subdirectories and capsulates the functionality in a file.
first arg: File Pattern; e.g ‘*.php’
second arg: pattern to search for; e.g. “find string”
third arg: replace string; e.g. “replace string”
The script still fails on filenames, that contain spaces. Any ideas what’s wrong?
=============================================
Paste this into a file ‘renall’ and make it executable (chmod u+x renall):
#!/bin/sh
if [ $# -lt 3 ] ; then
echo -e “Wrong number of parameters.”
echo -e “Usage:”
echo -e ” renall ‘filepat’ findstring replacestring\n”
exit 1
fi
#echo $1 $2 $3
for i in `find . -name “$1″ -exec grep -l “$2″ {} \;`
do
mv “$i” “$i.sedsave”
sed “s/$2/$3/g” “$i.sedsave” > “$i”
echo $i
#rm “$i.sedsave”
done
By Tobias on Jul 17, 2003
Sorry, I’m new to Linux.
I just can’t seem to get it to work. I copy it to the directory, chmod it, and.. well, I guess my question is if I’m running it properly. Should there be any output?
By sean on Jul 18, 2003
Ah, nevermind. I got it to work. Thanks.
By sean on Jul 18, 2003
Thank you. I had previously found a solution that uses a similar syntax in Perl (in the Linux Cookbook), but it fails to escape characters properly. Your script works perfectly.
By Sleeper on Jul 29, 2003
Thanks for sharing this … was very useful.
By Harish Puranik on Sep 3, 2003
There is a nice little utility called rpl for this task. http://software.freshmeat.net/projects/rpl/
By Gergo on Oct 26, 2003
That rpl utility was very useful…it did exactly what I needed. Thanks!
By Michael Sewell on Nov 11, 2003
Useful little script, thanks
By Mario on Nov 24, 2003
Thank you, thank you, thank you!
Just what I needed.
By Aleda Freeman on Dec 3, 2003
This is great! Thanks for the tip!
By Grant on Jan 16, 2004
Nice little script, thanks.
By Nick Gushlow on Feb 11, 2004
Wonderful! Thanks!
By Mandy on Apr 21, 2004
Just what I was looking for! THX!
By Sway on Apr 21, 2004
Wow! How easy. Thanks!!
By Megan on May 4, 2004
The following works for me. The command on the web page you reference has an error (see my comment there). It should be:
find ./ -type f -exec sed ’s/string1/string2/’ {} \;
This command visits every file in . and it’s subdirectories and makes the substitution.
By scott on May 22, 2004
oops, forgot the -i option to make sed edit the file in-place:
find ./ -type f -exec sed -i ’s/string1/string2/’ {} \;
By scott on May 22, 2004
Thanks a bunch! This is exactly what I needed
Will save me tons of repetitive, mindless work heh
By KristyX on Nov 4, 2004
Be sure you replace any backticks (the character next to the number 1 on a keyboard) with single quotes. Certain Wordpress themes like to replace these.
By Johntron on Mar 27, 2008
re that script:
if [ $# -lt 3 ] ; then
echo -e “Wrong number of parameters.”
echo -e “Usage:”
echo -e ” renall ‘filepat’ findstring replacestring\n”
exit 1
fi
#echo $1 $2 $3
for i in `find . -name “$1? -exec grep -l “$2? {} \;`
do
mv “$i” “$i.sedsave”
sed “s/$2/$3/g” “$i.sedsave” > “$i”
echo $i
#rm “$i.sedsave”
done
just tried it but when i use it the filepat arg is expanded by the shell before being passed to the script.
eg. mren *.xml find replace
will expand the args so $1 = a.xml, $2=b.xml … $27=find, $28=replace
quoting the *.xml didn’t help so i had to revise the script to take find and replace args first then iterate through the remaining args.
or was there an easier way to sort that wildcard file pattern expansion issue?
By Mark on Apr 14, 2008
Thanks.
By JC on May 17, 2008
What would be the best way to search and replace all the code between tags?
Search:
>html/htmlhtml/html<
This would also need to be done recursively.
By cg on Jun 19, 2008
I have a query
find $1/ | xargs grep -l $2 > tempf
What is this doing
By devarani.r on Jul 10, 2008