Mass File Renamer: By Number Sequence
Posted 09-13-2008 at 09: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"