Change filenames recursively

Hello,

I made a mistake in a script and now need to go back and change allot of filenames. I need to change "v4" in filenames to "v3". I was thinking of something like this.

#!/bin/bash

FILELIST=$(ls -f -R *)

for FILE in $FILELIST
do

   # create new filename
   NEW_FILE_NAME=$(echo $FILE | sed 's/v4/v3/g')

   # if a substitution was made
   if [ "$NEW_FILE_NAME" -ne "$FILE" ]; then

      # copy file to new name
      cp $FILE $NEW_FILE_NAME

      # remove original file
      rm $FILE
   fi

done

There are a rew issues with this approach. I'm not sure that ls -R -f is the best way to retrieve the list of files and since this will run recursively, I need to do some testing to make sure I don't do more harm the good. I'm also not sure about the ls -f option as far as filenames and paths go since I'm not changing directories.

Any suggestions?

LMHmedchem

You can do something like this:

#!/bin/bash

for file in *v4*
do
        echo mv "$file" "${file//v4/v3}"
done

Remove echo and rerun if output looks OK.

1 Like

This does not appear to work recursively, at least the echo version only gave output for files in pwd. This will need to work down through a fairly deep file tree to be practical.

LMHmedchem

This should work as long as you don't have and directory names with v4:

find . -iname "*v4*" -type f -print | while read file
do
    echo mv "$file" "${file//v4/v3}"
done

Otherwise this is less efficient but safer:

find . -iname "*v4*" -type f -print | while read file
do
   pth=$(dirname "$file")
   fl=$(basename "$file")
   echo mv "$file" "${pth}/${fl//v4/v3}"
done
1 Like

That worked nicely. It took a few minutes to run, but that was still the quickest way to correct the gaff.

LMHmedchem

You could speed it up a little (eliminating two utility invocations per file processed) by changing:

   pth=$(dirname "$file")
   fl=$(basename "$file")

to:

   pth="${file%/*}"
   fl="${x##*/}"
1 Like