Find and Replace in multiple files (Shell script)

hi guys,

Suppose you have 100 files in a folder and you want to replace all occurances of a word say "ABCD" in those files with "DCBA", how would you do
it ???

jatin

hi,

try this,

cd <your_folder>
ls > out.sh

vi out.sh

:%s/^/perl -pi -e 's\/ABCD\/DCBA\/' /

save and exit

sh out.sh

and bingo....

"perl -pi -e 's/abcd/dcba/' filename" will basically do the substitution and listing all the files in a file then prepending this string in front of each filename, will produce a shell script out.sh which would run this perl command on each of the files.

hope it helps
asif

If I understand what you're asking, this code should do what you want (ksh):

cd your_pathname
for i in `lx`; do
FOUND=`grep ABCD $i`
if [ "$FOUND" ]
then
TMP=./tmpfile_$$
sed -e 's/ABCD/DCBA/g' < $i > $TMP
mv $TMP $i
else
echo "The file $i does not include the word ABCD"
fi
done

This script reads each file in your_pathname, searches for the string ABCD, and either replaces it with DCBA or alerts you that the string ABCD was not found.

This is a bit simplier.

for y in `ls *`;
do sed "s/ABCD/DCBA/g" $y > temp; mv temp $y;
done

well there are so many different ways of doing it.

but what i am suggesting is why unnecessary create a temporary file when you can do without.

also, any suggestions from anyone, which of the above mentioned methods would be fastest.

I would bet that peter's is faster...

You could make it a split second faster by getting rid of the `ls *` though...

If could just be:
for y in *
since the shell will expand the * into all of the file names...
If you had directories in there, you'd want to use "find" to get only the files...

remember you are redirecting output to a file and then moving the file back to the original
what if the file sizes are of the order of tens of MBs.
secondly, the shell script would compulsorily do it for all the files in the directory.
but while using a file, you can customize your renaming process.

hey

thanks all of u ur replies were really helpful for me.
thanks to peter whose reply was the one really helped but everyones replies where helpful if anyone has anything similar to this can jump in with a solution in regards to this.

thanks & rgds
jatin :smiley:

the command ls * may fail in case of very large number
of files (several thousands).. in those cases the shell expands * into so many filename tokens that, ls may not be able to take in... see ls manual for largest number of filename arguments it can take...

this is the same case with any program which takes file names for its arguments (ls or otherwise)...

though for most cases what Peter says suffices :slight_smile:

Perderabo had said in an earlier thread that that problem can be avoided by dropping the asterisk (*).

So you could use this in Peter's script:
for y in `ls`;

No I didn't. The backticks ask the shell to run the command inside and then place the output in the command line. When you have too many files to fit in a command line, you need to do this:

ls | while read filename ; do

Here the output from the "ls" comannd get fed into the while loop line by line.

Oops - didn't mean to stick words in your mouth. :o

I was referring to this post.

I assumed that meant "ls" could always be substituted for "ls *" and everything would be fine. So actually this would work in Peter's script:

ls | while read y; do
sed "s/ABCD/DCBA/g" $y > temp; mv temp $y;
done

I used the same script

for y in `ls *`;
do sed "s/ABCD/DCBA/g" $y > temp; mv temp $y;
done

and it worked fine for finding and replacing strings in all files of the given path.

I'm trying to replace a sting which consists of path

say instead of ABCD i have to replace c:/mydocuments/pictures to
d:/mypics/personal , as metacharacters wont be searched in unix this script is failing to replace the sting which has a path in it.

i tired giving the path in single quotes and double quotes, but i see error

sed : garbled and all the contents of the files are erased
:confused:.

Is there any other way to work this out.

Thanks

When using "sed" for replacements, like this:

sed -e 's/AAA/BBB/g'

the separator (slash "/" in this case) can be any character. Since you have slashes in your replacement text, you should use some other character, preferably one that will not be used in the search or replacement text.

# These are all equivalent:
sed -e 's/AAA/BBB/g'
sed -e 's!AAA!BBB!g'
sed -e 's+AAA+BBB+g'