Batch renomeando arquivos do Terminal

1

Eu tenho alguns arquivos .mp3 que têm sinais $ no final das extensões que eu quero remover, eles são nomeados:

1.mp3$$
2.mp3$$
etc.

e eles devem ser

1.mp3
etc.

Eu tentei

for f in *; do a="(echo $f | sed s/mp3$$/mp3/)"; mv "$f" "$a"; done

mas isso deu a mensagem de erro

mv: rename 1.mp3$$ to (echo 1.mp3$$ | sed s/mp3582/mp3/): No such file or directory

para cada arquivo.

Depois de ler a resposta para isso

for i in *mp3$$; do mv "$i" "mp3"; done

mas isso não só não funcionou, como resultou em todos os arquivos, exceto um sendo excluído, e apenas um arquivo foi deixado chamado "mp3". Ele também deu a mensagem de erro de

mv: rename *mp3582 to mp3: No such file or directory
Felizmente eu ainda tenho os arquivos originais e ainda quero renomeá-los, mas como mudar "mp3 $$" para "mp3" pela linha de comando?

Além disso, por que o segundo comando acima resultou em todos os arquivos, exceto um que está sendo excluído?

E por que as mensagens de erro contêm a seqüência "3582", que não está em nenhum dos nomes dos arquivos?

P.S. Eu também já tentei usar \ $ em vez de $ no comando para escapar do caracter $, mas isso também não funcionou.

    
por LB7979 10.01.2018 / 10:34

3 respostas

4

$$ expande para o ID do processo do shell em todos os shells compatíveis com POSIX.

A alteração de *.mp3$$ arquivos para *.mp3 pode ser feita assim:

for i in *.mp3\$\$; do mv -i "$i" "${i%%\$\$}"; done 

Sua segunda linha de comando foi aparentemente executada por um shell com um PID de 582, então foi expandida para:

for i in *mp3582; do mv "$i" "mp3"; done

Então, como nada provavelmente corresponderia à expressão curinga, o loop seria executado apenas uma vez com a expressão curinga colocada como está na variável $i :

mv "*mp3582" "mp3" 
mv: rename *mp3582 to mp3: No such file or directory

Sua segunda tentativa também renomeia cada arquivo para o nome de arquivo fixo "mp3", sobrescrevendo qualquer arquivo anterior com esse nome, se "mp3" não for um diretório que já existe. Isso pode explicar por que todos os arquivos, exceto um, foram excluídos, se você também tentou usá-lo no formulário de escape:

for i in *mp3\$\$; do mv "$i" "mp3"; done

Isso faria:

mv <filename1>.mp3$$ mp3
mv <filename2>.mp3$$ mp3   # overwrites the previous "mp3"
mv <filename3>.mp3$$ mp3   # overwrites the previous "mp3" again
...

Sua tentativa original é realmente solucionável:

for f in *; do a="(echo $f | sed s/mp3$$/mp3/)"; mv "$f" "$a"; done   # your version
for f in *; do a="$(echo \"$f\" | sed s/mp3\$\$/mp3/)"; mv "$f" "$a"; done    # fixed version

Um comando ou pipeline dentro de apenas parênteses não será executado: você precisará da construção $( ... ) para isso. Adicione aspas duplas em torno dele para manipular a saída que pode conter espaço em branco, ponto-e-vírgula ou outros caracteres complicados.

Em seguida, os caracteres $ dentro do $( ... ) passarão pelo interpretador duas vezes : uma vez quando toda a linha de comando for analisada, outra vez quando a construção $( ... ) for analisada para execução. Em cada passagem, os caracteres com escape de contrabarra obtêm a barra invertida removida. Então, você precisará de barras invertidas duplas para preservar o "mp3 $$" do sed.

Além disso, $ f precisa de aspas duplas, caso os nomes dos arquivos contenham espaços em branco ou outros caracteres complicados ... e as aspas duplas precisam ser escapadas, pois estão dentro de outro conjunto de aspas duplas e queremos preservá-las para o $( ... ) pass.

    
por 10.01.2018 / 11:22
0

você pode experimentar este

for file in *.mp3\$\$; do mv -v "$file" "${file/.mp3\$\$/.mp3}"; done
    
por 10.01.2018 / 14:27
0

Usando o utilitário perl rename (não o comando rename de util-linux , que possui opções de linha de comando completamente diferentes e incompatíveis):

rename -n -v 's/\$+//g' *.mp3*

Isso removerá todos % caracteres$ de em qualquer lugar nos nomes de arquivos.

Se você quiser remover somente caracteres $ se eles estiverem no final dos nomes dos arquivos:

rename -n -v 's/\$+$//' *.mp3*

BTW, os comandos acima usam a opção rename -n como uma execução a seco para mostrar o que rename faria sem realmente renomear nada. Quando tiver certeza de que faz exatamente o que deseja, sem quaisquer conseqüências não intencionais, remova o -n da linha de comando. Opcionalmente, remova também a opção -v (verbose).

O utilitário perl rename está no pacote rename no Debian e nas distribuições derivadas. Este pacote contém o módulo CPAN Arquivo :: Renomear e o utilitário rename .

Versões anteriores do pacote perl no Debian costumavam incluir uma versão antiga do rename , com alguns bugs notáveis. Se você tem essa versão instalada, você deve instalar o pacote rename o mais rápido possível.

Esse rename baseado em perl às vezes também é instalado como file-rename ou prename . prename é geralmente a versão antiga de bugs.

    
por 11.01.2018 / 10:06