• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 1003
  • Last Modified:

Search and replace within file and directory NAMES on Solaris 8

Hi Experts,

I need to perform a search and replace of text within file and directory NAMES on Solaris 8 with the following conditions:
1. To be recursively performed on all files and directories within a directory.
2. Output a report on exactly were the text was replaced.
3. Interactive S&R would be a bonus, but not mandatory.

Many thanks!

Regards,
Tal.
0
traveh
Asked:
traveh
  • 9
  • 9
  • 7
2 Solutions
 
wesly_chenCommented:
Hi,
-----
#!/bin/sh

for files in `find <path to directory> -name <file or dir NAME>`
do
   dir_name=`dirname $files`
   New_file="$dir_name/<new name>"     <=== your new file/dir name
   mv $files $New_file
done
-----

Wesly
0
 
wesly_chenCommented:

# search_rename.sh <search filename> <replace name>
----search_rename.sh ---
#!/bin/sh

script_name=`basename $0`
if [ $# -ne 2 ]
then
    echo "Syntax Error!"
    echo "Usage:    $script_name <search filename> <replace filename>"
    exit 1
fi

rm -f /tmp/file_renamed   # clean the report file
search_name=$1     # read first parameter
replace_name=$2    # read second parameter

for files in `find <path to directory> -name $search_name`
do
   echo $files >> /tmp/file_renamed      # report which file/dir been renamed
   dir_name=`dirname $files`
   New_file="$dir_name/$replace_name"     <=== your new file/dir name
   mv $files $New_file
done
--------

Wesly
0
 
travehAuthor Commented:
Thanks, Wesly.

It's not exactly what I wanted, though...

What I need is to replace the text *within* the file or directory name.

For example (replace XXX with YYY):
abcd_XXX_efgh.sh -> abcd_YYY_efgh.sh

Thanks!
0
Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

 
wesly_chenCommented:
# search_rename.sh <search filename> <replace name>
----search_rename.sh ---
#!/bin/sh

script_name=`basename $0`
if [ $# -ne 2 ]
then
    echo "Syntax Error!"
    echo "Usage:    $script_name <search string> <replace string>"
    exit 1
fi

rm -f /tmp/file_renamed   # clean the report file
search_string=$1     # read first parameter
replace_string=$2    # read second parameter

for files in `find <path to directory> | grep $search_string`
do
   echo $files >> /tmp/file_renamed      # report which file/dir been renamed
   dir_name=`dirname $files`
   orig_filename=`basename $file`
   newfilename=`echo $orig_filename | perl -i -pe "s/$search_string/$replace_string/"`
   New_file="$dir_name/$newfilename"    
   mv $files $New_file
done
--------

Wesly
0
 
travehAuthor Commented:
It doesn't work... I get a multitude of these messages:

mv: ./DeploymentManager/installedApps/potterNetwork/adminconsole.ear/adminconsole.war/secure/status.jsp and ./DeploymentManager/installedApps/potterNetwork/adminconsole.ear/adminconsole.war/secure/./status.jsp are identical
mv: ./DeploymentManager/installedApps/potterNetwork/adminconsole.ear/adminconsole.war/secure/layouts and ./DeploymentManager/installedApps/potterNetwork/adminconsole.ear/adminconsole.war/secure/./layouts are identical
mv: ./DeploymentManager/installedApps/potterNetwork/adminconsole.ear/adminconsole.war/secure/layouts/addPropLayout.jsp
.
.
.

Tal.
0
 
wesly_chenCommented:
TYPO. Sorry my fat finger getting worse.

>   orig_filename=`basename $file`   <=== should be orig_filename=`basename $files`
>   newfilename=`echo $orig_filename | perl -i -pe "s/$search_string/$replace_string/"`
>   New_file="$dir_name/$newfilename"  

Wesly  
0
 
wesly_chenCommented:
# search_rename.sh <search filename> <replace name>
----search_rename.sh ---
#!/bin/sh

script_name=`basename $0`
if [ $# -ne 2 ]
then
    echo "Syntax Error!"
    echo "Usage:    $script_name <search string> <replace string>"
    exit 1
fi

rm -f /tmp/file_renamed   # clean the report file
search_string=$1     # read first parameter
replace_string=$2    # read second parameter

for files in `find <path to directory> | grep $search_string`
do
   echo $files >> /tmp/file_renamed      # report which file/dir been renamed
   dir_name=`dirname $files`
   orig_filename=`basename $files`
   newfilename=`echo $orig_filename | perl -pe "s/$search_string/$replace_string/"`
   New_file="$dir_name/$newfilename"    
   mv $files $New_file
done
----------

Wesly
0
 
yuzhCommented:
You want to rename the files/dirs, not the contains of the file, here's the one:

#!/bin/ksh
for File in `find /path-to-dir -name "*OLDstr*" `
do
    Newfile=$(echo $File | sed 's/OLDstr/Newstr/')
    mv $File $Newfile
done

exit

#End of script

If you want to keep a list of what have change, modify the script to:

#!/bin/ksh
# keep a the list in /path-to/list
find /path-to-dir -name "*OLDstr*"  -print > /path-to/list
for File in `cat /path-to/list`
do
    Newfile=$(echo $File | sed 's/OLDstr/Newstr/')
    mv $File $Newfile
done

exit

#End of script

   
0
 
yuzhCommented:
To get a reliable result, it is better to rename the files first, then rename the dir from
bottom up, modify the script to:

#!/bin/ksh
# keep a the list in /path-to/list
find /path-to-dir  -type f -name "*OLDstr*"  -print > /path-to/list
for File in `cat /path-to/list`
do
    Newfile=$(echo $File | sed 's/OLDstr/Newstr/')
    mv $File $Newfile
done

# Now do the dirs
#keep the dir list
find /path-to-dir  -type d -name "*OLDstr*"  -print | sort -r > /path-to/dirlist

for Dir in `cat /path-to/dirlist`
do
    Newdir=$(echo $File | sed 's/OLDstr/Newstr/')
   mv $Dir $Newdir
done

exit

#End of script


0
 
travehAuthor Commented:
Hi Yuzh,

A couple of questions:

1. In what way is your version different than Wesly's (except for the renaming of files before dirs)?
2. Why would renaming the files before the directories give better results?
3. Is that a kornshell version only, or would it work on cshell?

Thanks,
Tal.
0
 
yuzhCommented:
1. ) find commad locate target file/dir without have to use grep.
      youdon't have to worry about extra process to seperate path and file names
      ...

2) If you rename the dirname before rename the file, when you need  to rename
    the file, the path produced by "find" become invalid (it changed!)

3) ksh  shell syntax different from csh/tcsh, eg:
    for loop
    and
     var=value  etc

    for csh/tcsh becomes:
    foreach ...
    set var=...
    etc...etc...
0
 
wesly_chenCommented:
Hi,

  The reason I use "grep" because I want ot use variable $search_string, which I cannot
do it like "find . -name "*$search_string*".

   The second, in yuzh's script:
-------------
find /path-to-dir  -type f -name "*OLDstr*"  -print > /path-to/list
for File in `cat /path-to/list`
do
    Newfile=$(echo $File | sed 's/OLDstr/Newstr/')    <=== This might fail
    mv $File $Newfile
done
-------------
   When your full path of file is like  /123xxx/345xxx/654xxx, and you want to rename to
/123xxx/345xxx/654yyy first. But the script will rename to /123yyy/345yyy/654yyy, which the
path /123yyy/345yyy/ does not exist.

Wesly
0
 
wesly_chenCommented:
Hi,

   I take yuzh's suggestion to modify my script as follow:

# search_rename.sh <search filename> <replace name>
----search_rename.sh ---
#!/bin/sh

script_name=`basename $0`
if [ $# -ne 2 ]
then
    echo "Syntax Error!"
    echo "Usage:    $script_name <search string> <replace string>"
    exit 1
fi

rm -f /tmp/file_renamed   # clean the report file
search_string=$1     # read first parameter
replace_string=$2    # read second parameter

for files in `find <path to directory> -type f | grep $search_string`
do
   echo $files >> /tmp/file_renamed      # report which file/dir been renamed
   dir_name=`dirname $files`
   orig_filename=`basename $files`
   newfilename=`echo $orig_filename | perl -pe "s/$search_string/$replace_string/"`
   New_file="$dir_name/$newfilename"    
   mv $files $New_file
done

echo "##### Replaced Direcories #####" >> /tmp/file_renamed

for dirs in `find <path to directory> -type d| sort -r| grep $search_string`
do
   echo $dirs >> /tmp/file_renamed      # report which file/dir been renamed
   parent_dir=`dirname $dirs`
   base_dir=`basename $dirs`
   newdirname=`echo $base_dir| perl -pe "s/$search_string/$replace_string/"`
   New_dir="$parent_dir/$newdirname"    
   mv $dirs $New_dir
done
----------

   Thanks to yuzh's suggestion.

Regards,

Wesly
0
 
yuzhCommented:
Wesly's new version (http#12726436) correct the mistake we made in the previous comment.
(eg, my sed statement mix up the PATH, and his version of "find" mix dir with files).

I would still use:
find /path-to-dir  -type f -name "*OLDstr*"  
instead of "find + grep", one process vs two.

the same goes with the dirs.

Cheers!
0
 
travehAuthor Commented:
To "grab the stick from both ends", could I use something like:

find_string = "*$1*"
find /path-to-dir  -type f -name $find_string

?  
0
 
yuzhCommented:
since you are using *, you need to quote it:

find_string = "*${1}*"
find /path-to-dir  -type f -name "$find_string"
0
 
travehAuthor Commented:
BTW,

Using Wesly's last script I'm still getting these:

mv: ./AppServer/config/cells/potterNetwork/applications/DefaultApplication.ear/deployments/DefaultApplication/META-INF/was.policy and ./AppServer/config/cells/potterNetwork/applications/DefaultApplication.ear/deployments/DefaultApplication/META-INF/was.policy are identical
mv: ./AppServer/config/cells/potterNetwork/applications/DefaultApplication.ear/deployments/DefaultApplication/META-INF/MANIFEST.MF and ./AppServer/config/cells/potterNetwork/applications/DefaultApplication.ear/deployments/DefaultApplication/META-INF/MANIFEST.MF are identical

0
 
yuzhCommented:
We need to debug the script, add "set -x" to the script:

#!/bin/ksh
set -x


Pay attension to the values of
search_string=$1     # read first parameter
replace_string=$2    # read second parameter

make sure they all spell the same in the whole script.

check the values of  $New_file and $New_dir
0
 
travehAuthor Commented:
I'm currently running Wesly's version (on csh) - I think "set -x" won't work there.

Is there a corresponding "set debug" command for csh?
If not - can you send me a version for ksh? (I don't know if there are syntax differences between the two apart from what you sent me before)

Thanks!
Tal.
0
 
yuzhCommented:
It is possible to debug a script by adding the -x flag to the shell executable:
   % csh -x scriptname arguments

BTW, I'm currently running Wesly's version (on csh) - I think "set -x" won't work there.

     if you out:

#!/bin/ksh

as the first line of the script, and

set -x

as the 2nd line of the script
it should work, the script will run use ksh syntax.

All tthe script syntax we post are  sh/ksh/bash syntax, not csh/csh, please see http:12725092

in csh you still can run script written in other shell syntax as long as it has something like

#!/path-to/shell

0
 
wesly_chenCommented:
I've checked the script without error.
Howvever, if there is the file/directory name are the same as the one whiuch you are going to change to, then you will got "are identical"
issue.

So, I add the exist file/dir check as follow:

# search_rename.sh <search filename> <replace name>
----search_rename.sh ---
#!/bin/sh

script_name=`basename $0`
if [ $# -ne 2 ]
then
    echo "Syntax Error!"
    echo "Usage:    $script_name <search string> <replace string>"
    exit 1
fi

rm -f /tmp/file_renamed   # clean the report file
rm -f /tmp/exist_file  # clean the exist file
search_string=$1     # read first parameter
replace_string=$2    # read second parameter

for files in `find <path to directory> -type f | grep $search_string`
do
   echo $files >> /tmp/file_renamed      # report which file/dir been renamed
   dir_name=`dirname $files`
   orig_filename=`basename $files`
   newfilename=`echo $orig_filename | perl -pe "s/$search_string/$replace_string/"`
   New_file="$dir_name/$newfilename"    
   if [ -f $New_file -o -d $New_file ]
   then
     echo "$New_file has already existed" >> /tmp/exist_file
   else
      mv $files $New_file
   fi
done

echo "##### Replaced Direcories #####" >> /tmp/file_renamed

for dirs in `find <path to directory> -type d| sort -r| grep $search_string`
do
   echo $dirs >> /tmp/file_renamed      # report which file/dir been renamed
   parent_dir=`dirname $dirs`
   base_dir=`basename $dirs`
   newdirname=`echo $base_dir| perl -pe "s/$search_string/$replace_string/"`
   New_dir="$parent_dir/$newdirname"    
   if [ -f $New_dir -o -d $New_dir ]
   then
     echo "$New_dir has already existed" >> /tmp/exist_file
   else
      mv $dirs $New_dir
   fi
done
----------

Wesly
0
 
travehAuthor Commented:
BTW,

I thought csh and sh are the same... (?)
0
 
wesly_chenCommented:
sh is bourne SHell, the very earily shell in Unix world.
bash is Bourne Again SHell.

Type
man csh
man sh

to see the difference.

Wesly
0
 
travehAuthor Commented:
The last script Wesly sent worked! Thanks! :-D

I order to be able to reward your work, I will open a new topic for my other questions...

I will split the points - thanks Wesly and Yuzh, you are great!

Tal.
0
 
travehAuthor Commented:
P.S.

I hope I split the points fairly...

Good night!

Tal.
0

Featured Post

Concerto Cloud for Software Providers & ISVs

Can Concerto Cloud Services help you focus on evolving your application offerings, while delivering the best cloud experience to your customers? From DevOps to revenue models and customer support, the answer is yes!

Learn how Concerto can help you.

  • 9
  • 9
  • 7
Tackle projects and never again get stuck behind a technical roadblock.
Join Now