Depois da resposta de Rakesh Sharma, cheguei na direção certa depois de experimentar um pouco mais e dormir um pouco.
Por fim, criei o seguinte script:
#!/bin/bash
while IFS=";" read pattern replacement
do
if [[ ! -z $pattern ]]
then
echo "Checking files for pattern '$pattern'."
find ./files -name "*$pattern*" -type f | while read fpath
do
fname=$(basename "$fpath")
dname=$(dirname "$fpath")
echo " Found file '$fname' in directory '$dname'. Renaming to '${fname/$pattern/$replacement}'."
mv -- "$fpath" "$dname/${fname/$pattern/$replacement}"
done
fi
done < patterns.csv
Ele lê o arquivo pattern.csv
e percorre suas linhas preenchendo as variáveis $pattern
e $replacement
Na segunda etapa, todos os arquivos dentro de um diretório ./files
são encontrados, que correspondem ao padrão atual. Isso tem que ser feito para evitar a tentativa de renomear os arquivos novamente quando um segundo padrão corresponder, pois isso falharia. Finalmente, ele apenas renomeia o arquivo em si, não os diretórios que o contêm usando a substituição de parâmetros do shell.
O que não está funcionando é substituir as ocorrências que não diferenciam maiúsculas de minúsculas, mas eu posso viver com isso.