LinuxQuestions.org
LinuxAnswers - the LQ Linux tutorial section.
Go Back   LinuxQuestions.org > Blogs > ghostdog74
User Name
Password

Notices

Rating: 2 votes, 3.00 average.

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"
Posted in Uncategorized
Views 1941 Comments 0
« Prev     Main     Next »

  



All times are GMT -5. The time now is 12:51 AM.

Main Menu
Advertisement

My LQ
Write for LQ
LinuxQuestions.org is looking for people interested in writing Editorials, Articles, Reviews, and more. If you'd like to contribute content, let us know.
Main Menu
Syndicate
RSS1  Latest Threads
RSS1  LQ News
Twitter: @linuxquestions
identi.ca: @linuxquestions
Facebook: linuxquestions Google+: linuxquestions
Open Source Consulting | Domain Registration