16

I'm trying to find and replace a string in a folder of files.

Could someone possibly help me?

My script is as follows:

#!/bin/bash
OLD="This is a"
NEW="I am a"
DPATH="/home/user/test/*.txt"
BPATH="/home/user/test/backup/foo"
[ ! -d $BPATH ] && mkdir -p $BPATH || :
for f in $DPATH
do
  if [ -f $f -a -r $f ]; then
    /bin/cp -f $f $BPATH
    sed "s/$OLD/$NEW/g" "$f"
   else
    echo "Error: Cannot read $f"
  fi
done

Now this seems to find the string 'This is a' and replaces with 'I am a', but this only prints to screen.

I need it to replace in the files themselves.

Thanks

codaddict
  • 445,704
  • 82
  • 492
  • 529
terrid25
  • 1,926
  • 8
  • 46
  • 87

4 Answers4

32

Use the -i option of sed to make the changes in place:

sed -i "s/$OLD/$NEW/g" "$f"
    ^^
codaddict
  • 445,704
  • 82
  • 492
  • 529
  • Worked great! I knew I'd missed something. Thanks – terrid25 Dec 14 '10 at 10:33
  • Ok, is there an easy way to modify my shell script, so that it will check in subfolders? /home/user/test/xyz ? – terrid25 Dec 14 '10 at 10:43
  • #!bin/bash OLD="This is a" NEW="I am a" BPATH="/home/user/backup/foo" find . -name '*.shtml' -type f | while read filename do /bin/cp -f $filename $BPATH sed -i "s/$OLD/$NEW/g" $filename done – terrid25 Dec 14 '10 at 11:28
  • I am receiving this error when trying to use -i: sed: illegal option -- i Usage: sed [-n] [-e script] [-f source_file] [file...] – Dchris Sep 01 '17 at 14:36
  • 1
    @Dchris The `-i` option isn't entirely portable, though it's supported in some form on most platforms. On *BSD (including MacOS) you need `-i ''`; if you don't have `sed -i` at all, maybe try `perl -pi -e ` where a simple `sed` script can be use in Perl verbatim, but notice that the regex dialects differ (you mainly need to understand how backslashes need to be added or removed in some places). – tripleee Jul 20 '18 at 08:04
2

The output goes to screen (stdout) because of the following:

sed "s/$OLD/$NEW/g" "$f"

Try redirecting to a file (the following redirects to a new files and then renames it to overwrite the original file):

sed "s/$OLD/$NEW/g" "$f" > "$f.new" && mv "$f.new" "$f"
NPE
  • 486,780
  • 108
  • 951
  • 1,012
  • That creates a .text.new file and the original file, example.txt is overwritten and is blank. Any ideas why? – terrid25 Dec 14 '10 at 10:32
  • @user390426: It could be because aix didn't quote the variables `"$f.new"' (two places) and `"$f"`. Also, the `mv` shouldn't be unconditional. Instead, it should be `sed ... && mv ...`. – Dennis Williamson Dec 14 '10 at 11:07
  • Ok, I have now changed $OLD to be a URL and it returns an error: sed: couldn't open file ww.google.co.uk//g: No such file or directory the 'sed' command doesn't seem to like the // part of the url. Is there a way to overcome this? – terrid25 Dec 14 '10 at 12:48
  • 1
    @user390426: Change the delimiter in the `sed` command: `"s|$OLD|$NEW|g"`. – Dennis Williamson Dec 14 '10 at 15:13
0

Check this out

http://cs.boisestate.edu/~amit/teaching/handouts/cs-unix/node130.html

##########################################################
\#!/bin/sh

\# sed/changeword

prog=`basename $0`

case $# in
0|1) echo 'Usage:' $prog '<old string> <new string>'; exit 1;;
esac

old=$1
new=$2
for f in *
do
        if test "$f" != "$prog"

        then
            if test -f "$f"
            then
                sed "s/$old/$new/g" $f > $f.new
                mv $f $f.orig
                mv $f.new $f
                echo $f done
            fi
        fi
done

##############################################################
Lucas Zamboulis
  • 2,494
  • 5
  • 24
  • 27
Angshuman
  • 697
  • 8
  • 29
0

this is a snippet i use, it removes all stuff between APA and BEPA (across multiple lines, including removing APA, BEPA) in all files below current directory, exclude the .svn directory

find . \! -path '*.svn*' -type f -exec sed -i -n '1h;1!H;${;g;s/APA[ \t\r\n]*BEPA//g;p}' {} \;
JohnSmith
  • 4,538
  • 9
  • 25
  • 25