Você poderia fazer:
find . -name '*\[M]\[@0]\[0].dav.avi' -type f -exec sh -c '
for file do
echo mv "$file" "${file%"[M][@0][0].dav.avi"}.avi"
done' sh {} +
(remova echo se tudo estiver correto).
Ou se você quiser renomear todos os .dav.avi para .avi , mas também removerá um [M][@0][0] se houver:
find . -name '*.dav.avi' -type f -exec sh -c '
for file do
new=${file%.*.*}
new=${new%"[M][@0][0]"}.avi
echo mv "$file" "$new"
done' sh +
Essas são a sintaxe do POSIX e também funcionam com utilitários do busybox, portanto, devem funcionar em sinologia.
Algumas notas (com base nas observações da sua e de outras respostas):
- o padrão passado para
find -namedeve ser citado, caso contrário, pode ser expandido pelo shell. - você não pode usar
xargsnos nomes de arquivo, a menos que possa garantir que esses nomes de arquivo não conterão espaços em branco ou novas linhas ou citações ou barras invertidas. -
Use
printfem vez deechopara gerar dados arbitrários . - Deixar uma expansão variável sem aspas no contexto da lista tem um significado muito especial . Você não quer fazer isso aqui.
- O caractere
.é um operador de expressão regular especial, você precisa escapar em regexps se quiser que ele seja tratado literalmente. -
A sintaxe para ler uma linha com
readéIFS= read -r line, mas novamente não há garantia de que um caminho de arquivo seja feito de apenas uma linha. - Muitas vezes é melhor fazer
(cd -P -- "$dir" && find . ... -exec)do quefind -- "$dir" ... -execporque evita problemas com$dirvalores que sãofindpredicados ou começam com-e porque encurta os caminhos de arquivo passados para-exece assim permite passar mais.