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 -name
deve ser citado, caso contrário, pode ser expandido pelo shell. - você não pode usar
xargs
nos 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
printf
em vez deecho
para 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" ... -exec
porque evita problemas com$dir
valores que sãofind
predicados ou começam com-
e porque encurta os caminhos de arquivo passados para-exec
e assim permite passar mais.