Find and Replace String in filenames

I have thousands of files with no specific extensions. What I need to do is to search for a sting in filename and replace with other string and further search for second string and replace with any other string and so on. I.e.: I have multiple strings to replace with other multiple strings. It may be like:

  • "abc" in filename replaced with "def" *** String "abc" may be in many files
  • "jkl" in filename replaced with "srt" *** String "jkl" may be in many files
  • "pqr" in filename replaced with "xyz" *** String "pqr" may be in many files

I am currently using excel macro to get the file names in excel and then preserving original names in one column and replacing desired in the content copied in other column. then I create a batch file for the same. Like:

rename Path\OriginalName1 NewName1
rename Path\OriginalName2 NewName2

Problem with the above procedure is that it takes a lot of time as the files are many. And As I am using excel 2003 there is limitation on number of rows as well. I need a script in batch like:

replacestr  abc with def
replacestr  pqr with xyz

in a single directory. Will it be better to do in unix script?


If you can use Bash, then the following script should do what you want:

#!/bin/bash

(( $# != 2 )) && exit 1

for f in *; do
  newf="${f//$1/$2}"
  if [[ $f != $newf ]]; then
    mv "$f" "$newf"
  fi
done

It tries to replace filename with new string, if resulted filename doesn't match original, then it renames the file to resulted filename.

Usage, if saved as replacestr and given mode to be executed:

$ ./replacestr abc def

It will try to rename all. You can use [[ ! -f $f ]] to skip non-file. You can also wrap it in function and source it from your ~/.bashrc if you need this very often.


Any script you use could be potentially dangerous, but this worked for me on a limited scale (I just touched about 15 files and did a quick csv of abc,123 \n def,456 - etc.

With that out of the way, I would make a quick backup, test this on a few, and then roll it out.

Assumptions:
-The excel is exported to CSV with the format oldname,newname on each line
-You are in a bash shell.
-All in one directory
-They are all files (you can change the script to dirs by changing -type f to -type d

#!/bin/bash
inputfile=${1}
while read line
do
    IFS=',' read -a names <<< "${line}"
    for file in `find . -maxdepth 1 -type f -name "*${names[0]}*"`; do
        rename "s/${names[0]}/${names[1]}/" *
    done
done < ${inputfile}

This will work from the current directory (find .) and only work on 1 level(-maxdepth 1), items easily changed. Hope that at least gets you on the right track.

The important thing is this maintains the rest of your file name and only replaces the input string with the output. So file 123abc123.null with input of abc,999 would result in 123999123.null.

Just make it executable with chmod +x nameofmyscript.sh and execute it with ./nameofmyscript.sh input/file/location.csv