Script for batch renaming

What is wrong with this script to rename batch of similar files? For example renaming all *.txt files to *.tab .

$ for i in seq {01..10}; do touch ${i}.txt; done

$ ./rename.sh *.txt txt tab

Error:
mv: �01.txt� and �01.txt� are the same file.

Code is:

#!/usr/bin/bash 
# renames.sh 
# Usage: ./rename.sh regex match replacement 
 
pattern=$1 
match=$2 
replace=$3 
 
for i in $( ls *$pattern* );  
do 
 src=${i} 
 dst=$( echo ${i} | sed -e "s/${match}/${replace}/" ) 
 mv ${src} ${dst} 
done 

I am aware of the rename command, and read the thread. The job can be done with

for i in *.text*; do mv ${i} ${i%.text}.tab; done

but here I am trying to understand passing arguments in shell script.
Anybody give me a clue, please?
Thanks!

*.txt will be expanded by the shell to yield a long parameter list in which $1 is 01.txt , $2 is 02.txt . and $3 is 03.txt , resulting in sed -e s/02.txt/03.txt/ which doesn't substitute anything, so it will try to mv 01.txt 01.txt ---> error!

1 Like

Thanks!
Do you mean the problem is with the part: for i in $( ls *$pattern* ) ?
I changed the command line to:

$ ./rename.sh txt txt tab

which worked well, but it looks strange, doesn't it?!
And it has a bug as all the file names containing "txt" will be changed. That does not match what I intended.
I am still not quite sure about the expansion for *.txt Could you please elaborate more?

$ ./rename.sh \.txt txt tab

also worked, how is it working by a simple escape of the dot?

How about quoting the parameter?

./rename.sh "*.txt" txt tab
1 Like

It works without suprise, but I am wondering why it did not work if "*.txt" is not quotated, or \.txt dot is not escaped.

In the same directory where you ran your previous script, install this script:

#!/bin/bash
printf '$#=%d\n$0="%s"\n' $# "$0"
cnt=$#
for((i = 1; i <= $cnt; i++))
do	printf '$%d="%s"\n' $i "$1"
	shift
done

and compare the output you get when you run the commands:

./scriptname *.txt txt tab

./scriptname \*.txt txt tab

./scriptname "*.txt" txt tab

./scriptname '*.txt' txt tab

./scriptname "*".txt txt tab

./scriptname *".txt" txt tab
1 Like

Thanks Don!
Now I understand why my first command did not work, on which RudiC had explained *.txt will be expanded by the shell to yield a long parameter list in which $1 is 01.txt , $2 is 02.txt . and $3 is 03.txt , but I did not get it.
Thanks you both!