Ever run into a situation where you have a bunch of files that need to be renamed to a certain format? I constantly run into this and have been writing a quick bash for loop with a sed expression to mass rename the files. I noticed I was repeating this a lot, so I decided to make a little script out of it.
Anyone who downloads files that are named something like:
Something_-_01-01.ext, Something_-_01-02.ext, etc..
.. and wants to mass-rename them in a very flexible manner, like this (just as an example):
01 – Something – 01.ext, 01 – Something – 02.ext, etc..
.. and has way too little free time to do this one by one, then check this out.
Requirements:
- Linux or cygwin (Bash/sh interpreter + sed, tr)
- Knowledge of what a bash script is, and how to run it.
- Knowledge of sed and regex expressions.
Usage:
renamer.sh (-s<string>|-t<string>) [options] Options: -s : SED expression (e.g. "s/_/-/g" will replace "_" with "-" for all filenames) -t : Character translation map (e.g. "abc|def" will change "apple" to "dpple" ) -m : Move files, will not move files otherwise -r : Recursive renaming in child directories -a<str> : Set file match condition (current: *) -h|-H : Displays this usage screen
Examples:
- Something_-_01-01.ext » 01 – Something – 01.ext
renamer.sh -s"s/\(.[^_]*\)_-_\([0-9]*\)-\([0-9]*\)/\2 - \1 - \3/"
- Something_-_01_-_BlaBlaBla_-_01.ext » Something – 01 – BlaBlaBla - 01.ext
renamer.sh -t"_| " or.. renamer.sh -s"s/_/ /g"
Script:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 | #!/bin/sh APP=$0 search="" translate="" move=0 aFile="*" aRecurse=0 doUsage() { echo echo " $APP (-s|-t) [options]" echo echo " Options:" echo " -s : SED expression (e.g. \"s/_/-/g\" will replace \"_\" with \"-\" for all filenames)" echo " -t : Character translation map (e.g. \"abc|def\" will change \"apple\" to \"dpple\" )" echo " -m : Move files, will not move files otherwise" echo " -r : Recursive renaming in child directories" echo " -a : Set file match condition (current: $aFile)" echo " -h|-H : Displays this usage screen" echo } transformSed() { # perform sed op F=`echo "$1" | sed "$search"` # see if we have problems with sed op if [ $? -gt 0 ]; then echo "Problem detected with sed expression." >&2 return 1 fi # echo out the new string echo "$F" return 0 } transformTranslate() { INF=$1 declare -a TSTR echo "$translate" | tr "|" "\n" | while read T do if [ -z "$T" ]; then T=' ' fi TSTR[${#TSTR[@]}]="$T" if [ ${#TSTR[@]} -eq 2 ] ; then TF=${TSTR[0]} TT=${TSTR[1]} F=`echo "$INF" | tr "$TF" "$TT"` # see if we have problems with sed op if [ $? -gt 0 ]; then echo "Problem detected with translate expression." >&2 return 1 fi echo "$F" return 0 fi done } procFile() { F="$1" # skip dirs if [ -d "$F" ]; then return 1; fi # get original file path cpath=`dirname "$F"` # get original file name cfile=`basename "$F"` if [ ! -z "$search" ]; then # do sed transformation cfile=`transformSed "$cfile"` if [ $? -gt 0 ]; then return 2; fi fi if [ ! -z "$translate" ]; then # do translate transformation cfile=`transformTranslate "$cfile"` if [ $? -gt 0 ]; then return 2; fi fi # put filepath together again N="$cpath/$cfile" echo -e "\n BEFORE: '$F'\n AFTER: '$N'" # optionally move files to replaced name if [ $move -eq 1 ]; then # only if files have changed if [ "$N" != "$F" ]; then mv "$F" "$N" if [ $? -eq 0 ]; then echo "Moved Successfully" else echo "Problem while moving.." fi; else echo "No filename change detected.." fi fi } findFiles() { if [ $aRecurse -eq 1 ] ; then find . -name '* *' -o -name '*' -a -name "$aFile" else find . -maxdepth 1 -name '* *' -o -name '*' -a -name "$aFile" fi } # read arguments while getopts 'a:s:t:mrhH' o; do case $o in a) aFile="$OPTARG" ;; s) search="$OPTARG" ;; t) translate="$OPTARG" ;; m) move=1 ;; r) aRecurse=1 ;; h|H) doUsage exit 0 ;; :|\?) doUsage >&2 exit 1 ;; esac done # validate arguments if [ -z "$search" ] && [ -z "$translate" ]; then echo "No search/replace (-s ) or translate (-t ) operation was provided" >&2 doUsage >&2 exit 1 fi # begin processing findFiles | while read F do # process file procFile "$F" # see if we have problems, if so exit early if [ $? -gt 1 ]; then exit 1 fi done exit 0 |
