#!/bin/bash
# rn: rename multiple files according to several rules
# Based on the original work of Felix Hudson
# http://tldp.org/HOWTO/Bash-Prog-Intro-HOWTO-12.html
#
# Author Notice:
# Feel free to change and redistribute as long as you share the code
# and you keep these lines. Violators will not be prosecuted, but might
# feel bad about themselves =)
#
# Contact info:
# Eric G. Burgueño [nevermind85 (at) gmail (dot) com]
# http://malditaentropia.com.ar
#CHANGELOG:
#v.1.0: Implemented add prefix, suffix and replace string features.
#v.1.1: Replaced if switching by case
#v.1.2: Added listing renaming feature
#v.1.3: Implemented color output for better visuals
#set colors
y='\E[1;33m'
g='\E[1;32m'
b='\E[m'
#Usage message
ayuda(){
echo "Usage:"
echo " rn -p \"prefix\" file1 [file2] [file3]..."
echo " rn -s \"sufix\" file1 [file2] [file3]..."
echo " rn -r \"expression\" \"replacement\" file1 [file2] [file3]..."
echo " rn -l extension1 extension2"
echo "Of course, you can use wildcards."
echo "Remember to enclose strings within \"\"."
echo "\"expression\" and \"replacement\" patterns need to have special characters escaped like this:"
echo "rn -r \"dvdrip\\.fOv\" \"\" *avi"
echo
exit
}
#check for parameters
if [ $# -lt 3 ]; then
ayuda
fi
#First check for the various 'modes' that this program has.
#When the first ($1) condition matches, we execute that portion of the
#program and then exit.
case $1 in
# check for the prefix condition
-p )
#if [ $1 = "-p" ]; then
#make sure enought arguments were supplied
if [ $# -gt 2 ]; then
#we now get rid of the mode ($1) and prefix ($2)
prefix=$2 ; shift; shift
# this for loop iterates through all of the files that we gave the program
# it does one rename per file given
#note that we use $@ instead of $*, since the latter won't give us escape
#chars and quotes passed as a single argument (i.e. filename with spaces)
#we also enclose the $@ with "" so that all the quotes in the arguments
#do not expand themselves.
for file in "$@"
do
if test -f "$file"
then
echo -e "Moved $y$file$b to $g$prefix$file$b"
mv -i "$file" "$prefix""$file"
else
echo "File $y$file$b does not exist."
fi
done
#we now exit the program
exit
#if not mandatory arguments were supplied, show the usage
else
ayuda
exit
fi
;;
# check for the suffix condition
# the rest of this part is virtually identical to the previous section
# please see those notes
-s )
#if [ $1 = "-s" ]; then
if [ $# -gt 2 ]; then
sufix=$2 ; shift; shift
for file in "$@"
do
if test -f "$file"
then
echo "Moved $y$file$b to $g$file$sufix$b"
mv -i "$file" "$file$sufix"
else
echo "File $y$file$b does not exist."
fi
done
exit
else
ayuda
exit
fi
;;
# check for the replacement condition
-r )
#if [ $1 = "-r" ]; then
shift
# remove other information
expold=$1 ; expnew=$2 ; shift ; shift
# This for loop iterates through all of the files that we give the program
# it does one rename per file given using the program 'sed'
for oldname in "$@"
do
new="`echo "$oldname" | sed s/"$expold"/"$expnew"/g`"
if [ "$oldname" = "$new" ]; then
echo -e "Nothing done with $y$oldname$b. Probably string $y$expold$b was not found."
else
echo -e "Moved $y$oldname$b to $g$new$b"
mv -i "$oldname" "$new"
fi
done
exit
;;
#check for the list condition
-l )
#if [ $1 = "-l" ]; then
#this mode takes an array of sorted files from the first extension and
#a second array of sorted files from the second extension, in order to
#rename every file from the second array with the same name as the first
#array, but keeping the extension intact.
#Useful when you have: "Fringe - S01E04.srt" and "fringe.s01e04.xvid.lol"
#Many nasty things can go on with this so user confirmation is required.
#remove mode argument
shift
#save IFS to restore it later
OLDIFS=$IFS
IFS=$'\n'
#fill the two arrays
fileArray1=(`ls *$1`)
fileArray2=(`ls *$2`)
#simple check for array lenght (they should match)
if [ ${#fileArray1[@]} != ${#fileArray2[@]} ]; then
echo -e "File count for $y$1$b doesn't match file count for $g$2$b. No action taken."
echo -e "$y$1$b count: ${#fileArray1[@]}; $g$2$b count: ${#fileArray2[@]}"
exit 1
fi
#get array lenght
tLen=${#fileArray1[@]}
#get user confirmation
echo -e "This is a preview of how the renaming will take place:$y FROM$b /$g TO$b:"
for (( i=0; i<${tLen}; i++ ));
do
oldname=${fileArray2[$i]}
newname=`echo "${fileArray1[$i]}"|sed s/\.$1//`
echo -e "$y$oldname$b\n$g$newname.$2$b"
done
echo -ne "Confirm? [y/n]: "
read confirm
if [ $confirm = "y" ] || [ $confirm = "Y" ]; then
#cycle through the arrays and rename
for (( i=0; i<${tLen}; i++ ));
do
oldname=${fileArray2[$i]}
newname=`echo "${fileArray1[$i]}"|sed s/\.$1//`
if [ "$oldname" = "$newname.$2" ]; then
echo -e "Nothing done with $y$oldname$b. Destination file is the same."
else
echo -e "Moved $y$oldname$b to $g$newname.$2$b"
mv -i "$oldname" "$newname.$2"
fi
done
fi
IFS=$OLDIFS
exit
;;
esac