Mass File Renamer: By Number Sequence
Posted 09-13-2008 at 10:19 PM by ghostdog74
Code:
#!/bin/bash
## Change file names into a sequence of numbers.
NO_ARGS=0
E_OPTERROR=65
DEBUG=0
FNAME="f"
maxdepth=1
directory=`pwd`
set -o noglob
#---- Functions ------------#
usage() {
printf "Usage: `basename $0` [-D directory] [-M depth] [-s startseq] [-e endseq] [-p pattern] [-d] [-X] [filename(s)]\n"
cat << EOF
-D : starting directory. Default=current directory.
-M : max depth to recurse subdirectories (default=1), eg 1,2
-s : starting sequence, eg 1,01,001,0001
-e : ending sequence, eg 7, 12,1001. No effect with leading zeroes. Can be used with a tag
Eg -s 001 -e image20 -p "file" ==> files will be named image001 to image020, replacing the word "file" in the filename
-p : pattern to be substituted with the sequence. Can be simple shell patterns. eg [0-9], [a-z]
Use ".*" to specify ALL files to be changed.
-d : Debugging mode. Used to list all files to be changed, without changes taking effect
-X : Only check directory names, not file names
filename(s) : file names eg *.txt. If omitted, default to all files
Example:
1) -s 1 -e 12 -p "file" -d *.txt ===> change all name of text files
with pattern "file" with sequence starting from 1 till 12
2) -s 001 -e 12 -p ".*" ==> change ALL files to sequence 001 to 012
3) -s 00001 -e "file.30" -p "file" "*.txt" =====> change all text files with word "file" to file.00001 to file.00030
4) -s 01 -e "40.images" -p "file" "*.jpg" ====> change all jpg files with word "file" to "01.images" till "40.images"
EOF
}
#----------------------------#
if [ $# -eq "$NO_ARGS" ] # Script invoked with no command-line args?
then
usage
exit $E_OPTERROR # Exit and explain usage, if no argument(s) given.
fi
while getopts ":D:s:e:p:M:Xd" Option
do
case $Option in
D ) directory=$OPTARG
;;
s ) startseq=$OPTARG;;
e ) endseq=$OPTARG;;
p )
pattern=$OPTARG
[ -z "${pattern}" ] && pattern=".*"
;;
M )
maxdepth=$OPTARG
case ${maxdepth} in
0 | *[a-z]*| "") maxdepth=1;;
esac
;;
d ) DEBUG=1 ;;
X ) FNAME="d";;
* ) echo "Unimplemented option chosen."
exit;;
esac
done
shift $(($OPTIND - 1))
# get last argument
argument=$#
if [ $argument -eq 0 ];then
ext="*"
else
ext=$(eval echo \"\${${argument}}\")
fi
find "${directory}" -maxdepth "${maxdepth}" -type "${FNAME}" -name "$ext" -printf "%f:%h:%p\n" | \
awk -F":" -v startseq="$startseq" -v endseq="$endseq" -v pattern="$pattern" -v debug="$DEBUG" 'BEGIN{
q="\042"
match(endseq,"[0-9]") # get starting index of number
index_num=RSTART
match(endseq,"[^0-9]") #get starting index of not number
index_alpha=RSTART
numendseq=endseq
strendseq = endseq
gsub(/[^0-9]+/,"",numendseq) #get number
gsub(/[0-9]+/,"",strendseq) #get besides number
endseq=numendseq
lenseq = length(endseq)
lenstseq = length(startseq)
# generate sequence
for ( i = startseq+0 ; i<=endseq+0 ; i++ ){
_="0"lenstseq
num[++d]=sprintf("%0*d" , _ ,i)
}
}
$1 ~ pattern{
++e
if ( index_alpha > index_num ) {
s = gsub (pattern, num[e] strendseq , $1 )
}else {
s = gsub (pattern, strendseq num[e] , $1 )
}
if ( debug) {
print "mv -u " q $3 q " "q $2 "/" $1 q
}else {
cmd = "mv -u " q $3 q " "q $2 "/" $1 q
system(cmd)
}
if ( d==e ) { exit }
}'
Usage:
The script makes use of GNU find/awk. Maximum depth value passed to "find" is set to default 1 level. Issue -M <level> to recurse more than 1 level of subdirectories. File types is set to search for files by default. Issue -X to search for directory names. If -D <directory> is omitted, the script searches from current working directory onwards.
# Execute the script name without any arguments to show help.
> ./script.sh
# To see results before making actual changes, use the -d switch.
> ./script.sh -D /path/1 -M 2 -s 001 -e 100 -p image -d "*.txt"
# To rename files with extension ".txt" and word "image" in their file names with starting sequence 001 till ending sequence 100 and search directories for 2 levels.
> ./script.sh -D /path/1 -M 2 -s 001 -e 100 -p image "*.txt"
If the number of files found is less than 100, the script will stop.
# To rename all files in the current directory from 01 to 12 without traversing directories
> ./script.sh -s 01 -e 12 -p ".*"
# To rename all jpg files in the current directory with word "file" from 01 to 100 without traversing directories, and at the same time, tagging the word "image" in front of the ending sequence
> ./script.sh -s 01 -e image100 -p "file" -d "*.jpg"
# To rename all jpg files in the current directory with word "file" from 01 to 100 without traversing directories, and at the same time, tagging the word "image" behind the ending sequence
> ./script.sh -s 01 -e 100image -p "file" -d "*.jpg"









