Unix/Linux Find & Replace in Multiple Files

February 1, 2008 – 11:00 pm by gabe

Here’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. ]
  1. 24 Responses to “Unix/Linux Find & Replace in Multiple Files”

  2. Awesome little script; thanks for sharing.

    By Indrid Cold on Apr 25, 2003

  3. 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

  4. 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

  5. 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

  6. Ah, nevermind. I got it to work. Thanks.

    By sean on Jul 18, 2003

  7. 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

  8. Thanks for sharing this … was very useful.

    By Harish Puranik on Sep 3, 2003

  9. There is a nice little utility called rpl for this task. http://software.freshmeat.net/projects/rpl/

    By Gergo on Oct 26, 2003

  10. That rpl utility was very useful…it did exactly what I needed. Thanks!

    By Michael Sewell on Nov 11, 2003

  11. Useful little script, thanks :-)

    By Mario on Nov 24, 2003

  12. Thank you, thank you, thank you!
    Just what I needed.

    By Aleda Freeman on Dec 3, 2003

  13. This is great! Thanks for the tip!

    By Grant on Jan 16, 2004

  14. Nice little script, thanks. :)

    By Nick Gushlow on Feb 11, 2004

  15. Wonderful! Thanks!

    By Mandy on Apr 21, 2004

  16. Just what I was looking for! THX!

    By Sway on Apr 21, 2004

  17. Wow! How easy. Thanks!!

    By Megan on May 4, 2004

  18. 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

  19. 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

  20. Thanks a bunch! This is exactly what I needed :) Will save me tons of repetitive, mindless work heh

    By KristyX on Nov 4, 2004

  21. 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

  22. 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

  23. Thanks.

    By JC on May 17, 2008

  24. 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

  25. I have a query
    find $1/ | xargs grep -l $2 > tempf

    What is this doing

    By devarani.r on Jul 10, 2008

Post a Comment