То, что вы должны освежить в памяти - это подстановки строк. Все виды на самом деле. Баш очень хорошо с ними. Страница 105 (рецепт 5.18) поваренной книги Bash отлично подходит для этого.
#!/bin/bash
# Make it more flexible for improving command line parsing later
SWITCH=$1
EXTENSIONSRC=$2
EXTENSIONTGT=$3
# Match different cases for the only allowed switch (other than file extensions)
case $SWITCH in
-r|--)
# If it's not -r we limit the find to the current directory
[[ "x$SWITCH" == "x-r" ]] || DONTRECURSE="-maxdepth 1"
# Files in current folder with particular pattern (and subfolders when -r)
find . $DONTRECURSE -iname "*.$EXTENSIONSRC"|while read fname; do
# We use a while to allow for file names with embedded blank spaces
# Get canonical name of the item into CFNAME
CFNAME=$(readlink -f "$fname")
# Strip extension through string substitution
NOEXT_CFNAME="${CFNAME%.$EXTENSIONSRC}"
# Skip renaming if target exists. This can happen due to collisions
# with case-insensitive matching ...
if [[ -f "$NOEXT_CFNAME.$EXTENSIONTGT" ]]; then
echo "WARNING: Skipping $CFNAME"
else
echo "Renaming $CFNAME"
# Do the renaming ...
mv "$CFNAME" "$NOEXT_CFNAME.$EXTENSIONTGT"
fi
done
;;
*)
# The -e for echo means that escape sequences like \n and \t get evaluated ...
echo -e "ERROR: unknown command line switch\n\tSyntax: change <-r|--> <source-ext> <target-ext>"
# Exit with non-zero (i.e. failure) status
exit 1
esac
Синтаксис явно указан в сценарии. Я взял на себя свободу использовать соглашение --
, отделяющее ключи командной строки от имен файлов. Таким образом, он выглядит чище и проще в реализации.
NB: можно сгущать это дальше. Но здесь я пытался донести очко, а не выиграть запутанный конкурс Bash;)
PS: также обрабатывает нечувствительный к регистру материал теперь в части переименования. Однако я решил пропустить, если целевой файл уже существует. Может быть переписан как опция командной строки.