Renomeando arquivos recursivamente em sh

1

Eu uso o Synology como armazenamento para filmes de câmeras de CFTV. Depois de copiar um arquivo do sistema de CFTV para a Synology, eu o converto para o formato AVI. Então, meus arquivos têm nomes assim:

10.01.07-10.01.48[M][@0][0].dav.avi

Eu quero renomeá-lo recursivamente dos nomes acima para nomes como este:

10.01.07-10.01.48.avi 

Por favor, note que cada nome de arquivo consiste sempre na mesma parte [M][@0][0].dav.avi

Mas o problema é que não há nenhum comando rename no shell do Synology (é sh NOT bash )

Eu tentei usar o comando find em muitas sintaxes diferentes, mas sem sucesso. Você pode me ajudar a descobrir a solução?

    
por mackowiakp 08.10.2016 / 09:19

4 respostas

4

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 de echo 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 que find -- "$dir" ... -exec porque evita problemas com $dir valores que são find predicados ou começam com - e porque encurta os caminhos de arquivo passados para -exec e assim permite passar mais.
por 08.10.2016 / 11:17
0

Aqui está uma solução rápida usando sed para renomear os arquivos:

echo "10.01.07-10.01.48[M][@0][0].dav.avi" | sed 's/\[.*dav//'
10.01.07-10.01.48.avi

Eu não sei nada sobre o shell Synology, mas espero que sed esteja disponível!

Use (por exemplo) em um loop:

#!/bin/sh

for file in *avi; do
    newName=$(echo "$file" | sed 's/\[.*dav//')
    mv -v "$file" "$newName" 
done

Antes:

ls
09.01.07-13.11.48[M][@0][0].dav.avi
110.01.07-13.11.48[M][@0][0].dav.avi
12.01.07-13.11.48[M][@0][0].dav.avi

Executando o script:

./renameAvi.sh 
”09.01.07-13.11.48[M][@0][0].dav.avi” -> ”09.01.07-13.11.48.avi”
”110.01.07-13.11.48[M][@0][0].dav.avi” -> ”110.01.07-13.11.48.avi”
”12.01.07-13.11.48[M][@0][0].dav.avi” -> ”12.01.07-13.11.48.avi”

Depois:

ls
09.01.07-13.11.48.avi   12.01.07-13.11.48.avi
110.01.07-13.11.48.avi 


Editar: Se você quiser usar find uma maneira de implementar é como neste oneliner:

find . -name "*.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done
”./01.01.07-13.11.38[M][@0][0].dav.avi” -> ”./01.01.07-13.11.38.avi”
”./01.01.07-13.11.39[M][@0][0].dav.avi” -> ”./01.01.07-13.11.39.avi”
sed --version
sed (GNU sed) 4.2.2

find --version
find (GNU findutils) 4.4.2
    
por 08.10.2016 / 09:24
0

Para renomear arquivos recursivos você deve usar o comando abaixo.

find . -name "*dav.avi" | while read fileName; do newName=$(echo "$fileName" | sed 's/\[.*dav//'); mv -v "$fileName" "$newName"; done

Mude do script acima

(Eu não pude adicionar o comentário acima, então adicionando resposta aqui com pequenas mudanças no script que o maulinglawns já mencionou)

  • Use para pesquisar por * dav.avi, pois você terá muitos arquivos recursivos em seu armazenamento Synology, portanto, assim que esses arquivos forem renomeados, isso deverá ser feito novamente.
  • É uma alteração muito pequena, mas afetará se o sistema real tiver ~ GB de arquivos de dados.
por 08.10.2016 / 11:11
0

Finalmente descobri a solução. A renomeação é feita em duas etapas. É porque é possível que outros gravadores de CCTV transmitam arquivos com nomes diferentes, mas sempre no formato DAV. Então, simplesmente adicionando uma linha adicional semelhante à segunda, permitirá a cooperação com outros tipos de gravadores:

find $katalog -type f -name *.dav.avi | sed -e "p;s/.dav.avi/\.avi/" | xargs -n2 mv 2>/dev/null
find $katalog -type f -name *.avi | sed -e "p;s/\[M\]\[@0\]\[0\].avi/\.avi/" | xargs -n2 mv 2>/dev/null
    
por 08.10.2016 / 13:58