File: //usr/share/worker/scripts/aa.pattern_rename.sh
#!/bin/bash
# PATTERN_RENAME : Worker Utility by AArexx AAron
# /usr/local/share/worker/scripts/aa.pattern_rename.sh
#
# Script Version 0.2.3 (2013.10.27)
# 0.2.3 -- changed Pth to only append slash if it is not there already
# 0.2.2 -- changed DEFAULT action choices to Preview and Quit
# 0.2.1 -- added "Preview first 50" feature
# For Worker Version 2.7.0 +
# Release License: GPL
# www.gnu.org/copyleft/gpl.html
#
# written for portability using bash (2) shell
# (Some bash 2 specific function and syntax employed!)
# plus stock *niX commands (GNU) expr, mv
#
# NOTE: Requires a Worker Button be set up to collect
# file lists and name patterns from user selections in
# Worker interface; eg
#
# ## Get Source File Name Pattern
# script:
# [push at stack 1] [{Rs{Enter Match *Pattern* for Renaming:}{*{uf}*}}]
#
# ## Get Output Replacement String
# script:
# [push at stack 2] [{Rs{Enter Replacement String for "{top 1}":}{{top 1}}}]
#
# ## run this script
# own command [++ Run In Terminal, Wait For Key ]
# /usr/local/share/worker/scripts/aa.pattern_rename.sh {p} {top 1} {top 2} {uA}
# [if flag added then: {dir}/scripts/aa.pattern_rename.sh]
#
# ## Reload the directory listing in Worker
# Reload
#
# Script acts on the SELECTED files and links that match the Source Pattern.
#
# Script confirms directory write permission, checks File (or Link)
# type and checks for existing named files before "mv" is attempted.
#
# Script accepts and properly handles most any file name regardless
# of white space and unusual characters. The only "reserved" char is
# the "*" in the pattern definitions, which is allowed at the *ends*
# of the Match and Replacement strings.
#
# This is one of my more involved bash script attempts to
# date. Improvement ideas, code obfuscations, style tips
# and feature suggestions welcome: <aaron@pd.org>
#####============================
##=== Set Error Exit routine...
E_bugout()
{
echo "============================="
echo $1
echo "============================="
exit $E_err
}
#####============================
## Script flags
E_err=1
Prvw=0
#####
# Check args from Worker...
if [ $# -lt 4 ];
then
E_bugout "User Cancelled"
fi
#####
# Note the Specs
Pth="$1"
if [ $(expr substr "$Pth" ${#Pth} 1) != "/" ]; then
Pth="$Pth/"
fi
Lenpth=${#Pth}
Patsrc="$2"
Patout="$3"
Argcnt=$#
Lyncnt=$( expr $Argcnt - 3 )
##=====================================
## Validate DIR write permission.
## test
echo "The path is $Pth"
##
if [ ! -w "$Pth" ]
then
echo "-- No Write Permission:"
echo "-- $Pth"
E_bugout 'Error: Cannot rename without directory write permission.'
fi
#####
# Validate patterns and formatting
Lenps=${#Patsrc}
Lenpo=${#Patout}
Strsrc=$( echo "$Patsrc" | tr -d "[=*=]" )
Strout=$( echo "$Patout" | tr -d "[=*=]" )
Lensrc=${#Strsrc}
Lenout=${#Strout}
Difps=$( expr $Lenps - $Lensrc )
Difpo=$( expr $Lenpo - $Lenout )
if [ "$Strsrc" == "$Strout" ]
then
echo "- Pattern Strings: \"$Strsrc\" \"$Strout\""
E_bugout 'Error: Source and Replace are identical. Nothing to rename.'
fi
if [ $Difps -eq 0 ]
then
echo "- Source Pattern: \"$Patsrc\""
E_bugout 'Error: Need at least 1 "*" wild card at *head, tail* or *both*.'
fi
if [ $Difps -gt 2 ] || [ $Difpo -gt 2 ]
then
echo "- Patterns: \"$Patsrc\" \"$Patout\""
E_bugout 'Error: Max is two "*" wild cards at *head, tail* or *both*.'
fi
##====================================
##=== Define pattern_type function
##=== Pattyp 1=tail*, 2=*head or 3=*both*
pattern_type ()
{
local i=1
local Tst=0
local Typ=0
local Chr=""
until [ $i -gt $2 ] || [ $Tst -eq $3 ]
do
Chr=$( expr substr "$1" $i 1 )
if [ "$Chr" == '*' ]
then
let Tst=Tst+1
if [ $i -ne 1 ] && [ $i -ne $2 ]
then
echo "-n" "99"
return
fi
fi
let i=i+1
done
Typ=$( expr $i \<= $2 )
Typ=$( expr $Typ + $3 + $Tst - 1 )
echo "-n" $Typ
}
##### =================================
if [ $Lensrc -ne 0 ]
then
Pattyp=$( pattern_type "$Patsrc" $Lenps $Difps )
# Align Patout to match Patsrc
case $Pattyp in
1)
Patout="$Strout"'*'
;;
2)
Patout='*'"$Strout"
;;
3)
Patout='*'"$Strout"'*'
;;
99)
echo "- Pattern: \"Patsrc\" "
E_bugout 'Error: Wild card "*" must be at *head, tail* or *both*.'
;;
esac
else
Patsrc='*'
Pattyp=$( pattern_type "$Patout" $Lenpo $Difpo )
if [ $Pattyp -gt 2 ]
then
Pattyp=2
Patout='*'"$Strout"
fi
fi
#####
# Show the full renaming plan and
# get user confirmation or PREVIEW
echo "-------------------------------"
echo "- Rename any of $Lyncnt Selected File Entries from path:"
echo "- \"$Pth\""
echo "- which match source pattern" \""$Patsrc"\"
echo "- so that they match pattern" \""$Patout"\"
echo "-------------------------------"
# bash specific form here...
read -p 'CONTINUE, PREVIEW or QUIT? (c/P/q): ' -n1 RSVP ;
echo ""
echo "-------------------------------"
if [ "$RSVP" = "q" ] || [ "$RSVP" = "Q" ] ;
then
E_bugout "User Chose to Exit."
fi
if [ "$RSVP" != "c" ] && [ "$RSVP" != "C" ] ;
then
Prvw=1
fi
#####============================
##=== Main ReName Loop ...
Ref=3
Cnt=0
Lyn=""
while [ $Ref -lt $Argcnt ]
do
let Ref=Ref+1
Lyn="${!Ref}"
Fyl=${Lyn:$Lenpth}
if [ ! -h "$Lyn" ] && [ ! -f "$Lyn" ]
then
echo "-- Not File or Link:"
echo "-- $Lyn"
continue
fi
if [ $Lensrc -ne 0 ]
then
case $Pattyp in
1)
Nuname=${Fyl/#"$Strsrc"/"$Strout"}
;;
2)
Nuname=${Fyl/%"$Strsrc"/"$Strout"}
;;
3)
Nuname=${Fyl/"$Strsrc"/"$Strout"}
;;
esac
# Was pattern matched and replaced?
if [ "$Nuname" == "$Fyl" ]
then
echo "-- Skip No Match: $Fyl"
continue
fi
else
if [ $Pattyp -eq 2 ]
then
Nuname="$Fyl""$Strout"
else
Nuname="$Strout""$Fyl"
fi
fi
Nufile="$Pth""$Nuname"
if [ -e "$Nufile" ]
then
echo "-- Skip Existing: $Nufile"
continue
fi
let Cnt=Cnt+1
if [ $Prvw -eq 1 ]
then
Newfyl[$Cnt]="$Nufile"
Oldfyl[$Cnt]="$Lyn"
if [ $Cnt -lt 51 ]
then
echo "$Fyl" ' -->> ' "$Nuname"
else
if [ $Cnt -eq 51 ]
then
echo " ... etcetera ... "
fi
fi
else
mv '-f' "$Lyn" "$Nufile"
fi
done
if [ $Prvw -eq 1 ] ;
then
echo "-------------------------------"
read -p 'CONTINUE or QUIT? (c/Q): ' -n1 RSVP ;
echo ""
echo "-------------------------------"
if [ "$RSVP" != "c" ] && [ "$RSVP" != "C" ] ;
then
E_bugout "User Chose to Exit."
fi
Ref=0
while [ $Ref -lt $Cnt ]
do
let Ref=Ref+1
mv '-f' "${Oldfyl[$Ref]}" "${Newfyl[$Ref]}"
done
fi
#####
# Note the totals, Clean Up and Exit.
echo "-------------------------------"
echo "- Renamed $Cnt of $Lyncnt Files"
echo "-------------------------------"
exit 0
#------------#
# PS:
#
# One Line Multi Rename xxx.c to xxx.cc
# \ls *.C* | sed 's/\(.*\).C\(.*\)/mv & \1.cc\2/' | sh
#
# I know the general functionality of this script could be
# accomplished in one line via perl or sed or awk, but my
# goal was to make the process a tiny bit more friendly,
# comprehensible and intuitive for the not-a-super-guru
# newby-ish Linux users like myself.
# -- aarexx aaron