shell script to find and replace string in multiple files

I used the following script

cd pathname
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 with names etc. in all files of the given path.

I'm trying to replace a string which consists of path (location of file)

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 string which has a path in it.

now my script is

cd pathname
for y in `ls *`;
do sed "s/'c:/mydocuments/pictures'/'d:/mypics/personal'/g" $y > temp; mv temp $y;
done

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

sed: command garbled: s/'c:/mydocuments/pictures'/'d:/mypics/personal'/g

And all the contents of the files in the path are erased.

Also tried the following using sed -

sed -e "s!AAA!BBB!g"
sed =e "s+AAA+BBB+g"

as the string has / in the file location path

Is there any other way to work this out.

Thanks

Try

cd pathname
for y in `ls *`;
do 
   sed 's_c:/mydocuments/pictures_d:/mypics/personal_' $y > temp; mv temp $y;
done

Jean-Pierre.

below script sent the error

sed: command garbled:

There was an erroneous / in the sed command.
Previous post modified.

Jean-Pierre.

Single quotes become ordinary characters when inside double-quotes. So you can do this:

echo "that's OK"

and this is not an error or open-quote. So putting single-quotes inside a quoted sed-expression is OK, but is does not quote the text between them.

The code above by Jean-Pierre looks OK to me.

Now it works, one of the _ is missing in my sed command .

Thanks 2 all who responded

I tried the following script

cd pathname
for y in `ls *`;
do
sed 's_c:\mydocuments\pictures_d:/mypics/personal_' $y > temp; mv temp $y;
done

This script is working for all other paths mentioned with forward slash (i.e c:/mydocuments/pictures ).

As it has a back slash i need to save it with one more \ i.e \\ but using this is not working, instead getting Error (sed garbled).

Any solutions ?

Doubling \ works fine :

$ echo '  c:\mydocuments\pictures ' | sed 's_c:\\mydocuments\\pictures_d:/mypics/personal_'
  d:/mypics/personal 
$

Jean-Pierre.

used the script above modified for my needs:

cd deploy
for y in `ls *.xml`;
do
sed 's_OLD.VALUE_NEW.VALUE_' $y > temp; mv temp $y;
done

works great except one thing: it overwrites all xml files changing their time stamp. is it possible to have the script updating only the ones that have OLD.VALUEs?

Make the mv conditional.

Also lose the silly `ls *`

cd deploy
for y in *
do
  sed 's_OLD.VALUE_NEW.VALUE_' "$y" >temp
  if cmp temp "$y" >/dev/null
  then
    rm temp
  else
    mv temp "$y"
  fi
done

Thank you era, works like a charm

#!/usr/bin/perl
#bash#./ff.pl --prod \/opt\/ WebSphere5 --cob \/opt\/was6mig\/WebSphere5 -base

use File::Find;
use Getopt::Long;
#$dmPath="/scratch/optcob/cells.dmgr.tmp";
#Modify the Basepath with new copied WAS5 copied location.
$basePath="/opt/IBM/WAS6.1/IBMIHS/CI_CNV_CRD_HTTPServer";
$dmPath="/dm5"; # don't worry about this $basePath="/app/WebSphere6/profiles";
$tmpf="/tmp/tmpf";
sub ModFileByRegex {
my ($tok, $repl, $fpat, $Path) = (@);
my $cnt = 0;
sub fwanted {
-f &&
$File::Find::name =~ /$fpat/ && do {
open (INF, $File::Find::name) || die "cannot open $File::Find::name : $!";
open (TMPF, ">$tmpf") || die "cannot open $tmpf for writing: $!";
my @input = <INF>;
my $change = grep { s/$tok/$repl/g } @input;
if ($change > 0) {
close INF;
print TMPF @input;
close TMPF;
print "updating/saving copy of $File::Find::name\n";
rename $File::Find::name, $File::Find::name . ".org";
print `cp -p $tmpf $File::Find::name\n`;
$cnt++;
}
}
}
print "searching from $Path for $tok in files called $fpat\n";
find (\&fwanted, $Path);
return ($cnt);
}
sub findDirByRegex {
my ($tok, $repl, $Path) = (@
);
my $cnt = 0;
sub wanted {
-d &&
$File::Find::name =~ /$tok[\w\.]?$/ &&
push @DIRL, $File::Find::name;
}
print "Looking for directories from $Path called $tok\n";
find (\&wanted, $Path);
while ($_ = pop @DIRL) {
$src = $_;
s/$tok([\w\.]
)?$/$repl$1/;
print "rename $src, $\n";
rename $src, $
|| warn "could not rename last file, please check";
$cnt++;
}
return ($cnt);
}
%optctl = ();
GetOptions (\%optctl, "prod=s", "cob=s", "dmgr", "base");
print "options set:\n\n";
print "prod system (source system) :" . $optctl{"prod"} . "\n";; print "cob system (target system) :" . $optctl{"cob"} . "\n"; print "Do Deployment Manager\n" if ($optctl{"dmgr"} == 1); print "Do Base WebSphere\n" if ($optctl{"base"} == 1);
print "\n\n";
if ($optctl{"dmgr"} == 1) {
print "updating Deployment Manager XML files\n";
$cnt = ModFileByRegex ($optctl{"prod"}, $optctl{"cob"}, ".", $dmPath);
print "$cnt XML files were updated\n"; }
if ($optctl{"base"} == 1) {
print "updating WebSphere Base XML files\n";
$cnt = ModFileByRegex ($optctl{"prod"}, $optctl{"cob"}, ".
", $basePath);
print "$cnt XML files were updated\n"; }
if ($optctl{"dmgr"} == 1) {
print "updating Deployment Manager base Directory Names\n";
$cnt = findDirByRegex ($optctl{"prod"}, $optctl{"cob"}, $dmPath);
print "$cnt directory names updated\n"; }
if ($optctl{"base"} == 1) {
print "updating WebSphere base Directory Names\n";
$cnt = findDirByRegex ($optctl{"prod"}, $optctl{"cob"}, $basePath);
print "$cnt directory names updated\n"; }