Solved

Replacing a string in multiple files?

Posted on 2004-08-05
10
611 Views
Last Modified: 2010-04-21
Hi,
This is my first EE question. I've searched the Linux TA's before asking, but maybe I haven't been searching the right term, because I haven't come across anything that has helped me yet.

Basically, I need to edit a string in several webpages on several different domains, and doing this manually is very time consuming. I'm wanting a shell script to run that will search all the files in a directory, find the old string and replace it with the new string. I'm fairly new to linux and shell scripting, obviously, so please explain your solution so I can learn from your expertise as well as solve my immediate problem.

Thanks in advance. Love the site so far. I found it a week ago, and have learned a lot just from searching various topics...
0
Comment
Question by:heresy_is_progress
  • 4
  • 4
  • 2
10 Comments
 
LVL 36

Accepted Solution

by:
grblades earned 300 total points
ID: 11729382
Hi heresy_is_progress,
'sed' is a very usefull utility which will perform various edititing functions. One of which is a search and replace. Here is a quick example. I haven't tested it myself.

#!/bin/bash
allfiles=`ls -1`;
for file in $allfiles ; do
sed -e s/originaltext/replacewith/ $file > /tmp/tempfile
rm -f $file
mv /tmp/tempfile $file
done
0
 

Author Comment

by:heresy_is_progress
ID: 11729584
grblades,
Thanks for the prompt reply. I'm assuming I'll need to run this script from the directory that I'm editing, since there isn't anyewhere that tells it what directory to look for? if so, that isn't a problem; I just wanted to clarify before testing... thanks...
0
 
LVL 36

Expert Comment

by:grblades
ID: 11729647
Yes it works in the current directory.
0
 

Author Comment

by:heresy_is_progress
ID: 11729748
Awesome! it works. Another question, then you get the points:
can I define a variable to the newstring & oldstring? for example

#!/bin/bash
oldstring = '/path/to/oldfile/oldfile'
newstring = '/path/to/newfile/newfile'

allfiles=`ls -1`;
for file in $allfiles ; do
sed -e s/$oldstring/$newstring/ $file > /tmp/tempfile
rm -f $file
mv /tmp/tempfile $file
done

if that is do-able, is my syntax correct? thanks...
0
 
LVL 36

Expert Comment

by:grblades
ID: 11729834
I don't follow what you mean. Do you want to take the original string and the string to replace it with from a couple of text files?
If you do then you are almost correct but remember that the ` symbol evaluates the command so if you want to pull the contents of a file into a variable you have to do :-

oldstring = 'cat /path/to/oldfile/oldfile'
newstring = 'cat /path/to/newfile/newfile'

Note that sed is using the '/' character to separate parameters so the search or replace string cannot contain them. Or at least if it does you need to escape them.
The search string is also a regular expression (see man grep for some infor on regular expressions) so matching 192.168.1.2 will find 192.168.1.2 and 192.168.102 (since the . matches any character).
0
Find Ransomware Secrets With All-Source Analysis

Ransomware has become a major concern for organizations; its prevalence has grown due to past successes achieved by threat actors. While each ransomware variant is different, we’ve seen some common tactics and trends used among the authors of the malware.

 

Author Comment

by:heresy_is_progress
ID: 11729935
actually, I'm wanting to edit an absolute filepath that's calling up an obsolete include file in a php page. on the actual php script, I'm wanting to change:

include '/old/path/to/includefile';

to

include '/new/path/to/includefile';

so yes, I need to escape the forward slashes(/). What character do I use, a backslash(\)?
0
 
LVL 36

Expert Comment

by:grblades
ID: 11730118
Yes you use a backslash. I think you might need quotes around the expression also.

So:-
sed -e "s/\/old\/path\/to\/includefile/\/new\/path\/to\/includefile/" $file > /tmp/tempfile

regular expressions can get very complicated to look at quite quickly ;)
0
 

Author Comment

by:heresy_is_progress
ID: 11730416


"sed -e "s/\/old\/path\/to\/includefile/\/new\/path\/to\/includefile/" $file > /tmp/tempfile

regular expressions can get very complicated to look at quite quickly ;)"

I'll say. What are all those "'N's" and "V's"? jk...;-D

thanks grblades. I threw on a 50 point bonus for all your help...:-)
0
 

Expert Comment

by:miyako
ID: 12211846
I know this is closed, but the following script eliminates having to worry about the regular expression handling.  Since it uses $ substitution, your search and replace strings will not be treated as regexps.  So, you can safely include any characters, except you must "escape" the $ character with a backslash, otherwise it is considered a variable.

You can call this from the command line specifying the parameters, so there's no need to edit the script each time.  Have fun...

Note that in the unlikely event that you already have files named *.greplace, they will be deleted, since greplace uses them as the temporary file.  I could rewrite it with tmpfile....

#!/bin/bash
#
if [ -z "$1" ] || [ -z "$2" ] || [ -z "$3" ] || [ -z "$4" ] ; then
      echo
      echo "greplace performs a global search and replace on multiple files, recursing directories."
      echo
      echo "USAGE: greplace path filename_pattern search_string replace_string"
      echo "WHERE:"
      echo "        path : path to start search (greplace always recurses)"
      echo "        filename_pattern : pattern of filenames to search - ALWAYS enclose in quotes"
      echo "        search_string : string to search for (ALWAYS enclose in quotes, if it contains '\$' be sure to preceed with backslash."
      echo "        replace_string : string to replace search_string with (ALWAYS enclose in quotes, if it contains '\$' be sure to preceed with backslash."
      exit 192
fi

ALLFILES=`grep -l --directories=recurse --exclude=*~ --include="$2" "$3" "$1"`
echo "Replacing $3 with $4"
for FILE in $ALLFILES ; do
      echo "Processing ${FILE}..."
      rm ${FILE}.greplace &> /dev/null
      touch ${FILE}.greplace
      exec 3< "$FILE"
      while read THISLINE <&3 ; do
            echo "${THISLINE//$3/$4}" >> $FILE.greplace
      done
      exec 3>&-
      mv $FILE ${FILE}~
      mv $FILE.greplace $FILE
done
0
 

Expert Comment

by:miyako
ID: 12211858
Oh yeah...forward slashes need to be escaped as well...
0

Featured Post

What Is Threat Intelligence?

Threat intelligence is often discussed, but rarely understood. Starting with a precise definition, along with clear business goals, is essential.

Join & Write a Comment

Suggested Solutions

Have you ever been frustrated by having to click seven times in order to retrieve a small bit of information from the web, always the same seven clicks, scrolling down and down until you reach your target? When you know the benefits of the command l…
The purpose of this article is to fix the unknown display problem in Linux Mint operating system. After installing the OS if you see Display monitor is not recognized then we can install "MESA" utilities to fix this problem or we can install additio…
Excel styles will make formatting consistent and let you apply and change formatting faster. In this tutorial, you'll learn how to use Excel's built-in styles, how to modify styles, and how to create your own. You'll also learn how to use your custo…
In this seventh video of the Xpdf series, we discuss and demonstrate the PDFfonts utility, which lists all the fonts used in a PDF file. It does this via a command line interface, making it suitable for use in programs, scripts, batch files — any pl…

708 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

13 Experts available now in Live!

Get 1:1 Help Now