Substitua% 20 por um espaço em nomes de arquivos? [duplicado]

3

Eu tenho uma lista de arquivos que estão usando % 20 para indicar um espaço em seus nomes.

Atualmente, estou tentando fazer o seguinte para alterar todos eles de% 20 para um espaço "".

for x in *.txt
  do mv $x $(echo $x | sed -e 's/%20/ /')
done

Isso não é legal. Ele cospe isto:

usage: mv [-f | -i | -n] [-v] source target
       mv [-f | -i | -n] [-v] source ... directory

Mas faço o mesmo em algumas das minhas imagens quando as importo e funciona bem:

for x in *_MG*.CR2
  do mv $x $(echo $x | sed -e 's/_MG/_IMG/')
done

Esquecendo que um está usando .TXT e o outro é .CR2 , o que eu estou negligenciando aqui?

Tendo em mente que estou usando um laptop de trabalho, não posso adicionar o Homebrew para instalar qualquer software adicional. E é o Mac OS X para o SO.

    
por Danijel-James W 14.12.2014 / 07:41

3 respostas

4

Não há necessidade de usar sed, isso pode ser controlado pela expansão de parâmetros

mv -- "$x" "${x//%20/ }"

FWIW, eu estaria substituindo os %20 s por um sublinhado (ou algo assim); Eu odeio nomes de arquivos que contêm espaços. Mas eu acho que aprender a escrever scripts bash que podem manipular espaços e outros caracteres especiais em nomes de arquivos é uma coisa boa. :)

Como Izkata menciona nos comentários, é muito importante citar os parâmetros! Aspas duplas no bash (e shells relacionadas) não são meros delimitadores de strings, elas também significam que você não quer que a divisão de palavras ocorra. Portanto, se x contiver um nome de arquivo com um espaço, $x será tratado como dois argumentos, mas "$x" será tratado como um único argumento. Se usarmos aspas simples, inibiremos a expansão dos parâmetros, então '$x' apenas resultará em uma string literal contendo $x , que geralmente não é o que queremos. :)

PS. Obrigado ao Monsieur Chazelas por fornecer o -- ausente na minha linha de comando. -- indica o final das opções na lista de argumentos; sem ele, é possível que nomes de arquivos que iniciam com - sejam interpretados como opções.

    
por 14.12.2014 / 12:49
8

Use rename e substitua o %20 por um espaço em todos os tipos de arquivos:

$ rename -n 's/%20/ /g' *

File%20with%20in00.yA2 renamed as File with in00.yA2
File%20with%20in01.h9H renamed as File with in01.h9H
File%20with%20in02.CNR renamed as File with in02.CNR
File%20with%20in03.PuP renamed as File with in03.PuP
File%20with%20in04.js8 renamed as File with in04.js8
File%20with%20in05.KdZ renamed as File with in05.KdZ

No OS X, você pode usar uma ferramenta especializada, como o utilitário de renomeação baseado em Perl. você pode instalá-lo usando o popular gerenciador de pacotes Homebrew : brew install rename

Observação: remova a opção -n para realizar renomeação real.

    
por 14.12.2014 / 08:02
7

Como a saída do mv provavelmente terá espaços, você precisa colocar aspas duplas em torno do resultado para não tentar executar comandos no loop for como:

mv abc%20def abc def

em que mv tem muitos argumentos. Estes são os que te dão a mensagem usage: .

O que você deve fazer é:

for x in *_MG*.CR2
do 
  mv -- "$x" "$(printf '%s\n' "$x" | sed 's/_MG/_IMG/')"
done
    
por 14.12.2014 / 07:46