como renomear vários arquivos substituindo string no nome do arquivo? essa string contém um "#"

42

https://serverfault.com/questions/70939/how-to-replace-a-text-string-in-multiple-files-in-linux

https://serverfault.com/questions/228733/how-to-rename-multiple-files-by-replacing-word-in-file-name

https://serverfault.com/questions/212153/replace-string-in-files-with-fficient-file-extension

https://serverfault.com/questions/33158/searching-a-number-of-files-for-a-string-in-linux

Todos esses artigos mencionados responderam à minha pergunta. No entanto, nenhum deles funciona para mim. Eu suspeito que é porque a string que estou tentando substituir tem um # nela. Existe uma maneira especial de resolver isso?

Eu tenho um arquivo de imagem que foi substituído por # U00a9 durante uma migração de site. Estes são assim:

Lucky-#U00a9NBC-80x60.jpg
Lucky-#U00a9NBC-125x125.jpg
Lucky-#U00a9NBC-150x150.jpg
Lucky-#U00a9NBC-250x250.jpg
Lucky-#U00a9NBC-282x232.jpg
Lucky-#U00a9NBC-300x150.jpg
Lucky-#U00a9NBC-300x200.jpg
Lucky-#U00a9NBC-300x250.jpg
Lucky-#U00a9NBC-360x240.jpg
Lucky-#U00a9NBC-400x250.jpg
Lucky-#U00a9NBC-430x270.jpg
Lucky-#U00a9NBC-480x240.jpg
Lucky-#U00a9NBC-600x240.jpg
Lucky-#U00a9NBC-600x250.jpg
Lucky-#U00a9NBC.jpg

e eu quero mudar para algo assim:

Lucky-safeNBC-80x60.jpg
Lucky-safeNBC-125x125.jpg
Lucky-safeNBC-150x150.jpg
Lucky-safeNBC-250x250.jpg
Lucky-safeNBC-282x232.jpg
Lucky-safeNBC-300x150.jpg
Lucky-safeNBC-300x200.jpg
Lucky-safeNBC-300x250.jpg
Lucky-safeNBC-360x240.jpg
Lucky-safeNBC-400x250.jpg
Lucky-safeNBC-430x270.jpg
Lucky-safeNBC-480x240.jpg
Lucky-safeNBC-600x240.jpg
Lucky-safeNBC-600x250.jpg
Lucky-safeNBC.jpg

ATUALIZAR:

Todos esses exemplos começam com "LU00a9ucky, mas aqui estão muitas imagens com nomes diferentes. Estou simplesmente direcionando a parte" # U00a9 "da string para substituir por" safe ".

Comunidade
fonte
3
Então, o que você realmente tentou? Vejo que você se vinculou a algumas perguntas e disse que elas falharam, mas como elas falharam? IMO, o melhor exemplo usa o renamecomando Eu suspeito que seu renomear seria tão simples quanto rename -n 's/#/safeNBC/' *.jpg.
Zoredache
Eu tentei rename -n 's/#U00a9/safe/' *.jpge o comando foi aceito, mas nenhuma alteração ocorreu.
Claro, como você já viu na documentação que certamente revisou, esta -né a no actopção. O que permite ver se funciona antes de você realmente usá-lo. A saída na tela mostrou os possíveis novos nomes corretamente?
Zoredache
Peço desculpas por ter copiado e colado o seu exemplo sem prestar total atenção, fiz o comando renomear sem o -n. Acredito que o @DTK resolva o problema, não estava escapando do #.
Substituindo cadeias de nomes de arquivos no MacOS: superuser.com/questions/152627/…
Anton Tarasenko

Respostas:

64

Para substituir #por somethingelsenomes de arquivos no diretório atual (não recursivo), você pode usar o utilitário de renomeação GNU :

rename  's/#/somethingelse/' *

Caracteres como -devem ser escapados com a \.

Para o seu caso, você gostaria de usar

rename 's/#U00a9/safe/g' *

Observe que se você deseja operar apenas em uma certa seleção de arquivos, por exemplo, apenas *.jpg, ajuste a entrada final para corresponder a essa seleção:

rename 's/#U00a9/safe/g' *.jpg

Para executar um teste antes de alterar os nomes dos arquivos, use o -nsinalizador:

demo/> ls                               
Lucky-#U00a9NBC-125x125.jpg  
Lucky-#U00a9NBC-150x150.jpg 

demo/> rename -n 's/#U00a9/safe/g' *.jpg
rename(Lucky-#U00a9NBC-125x125.jpg, Lucky-safeNBC-125x125.jpg)
rename(Lucky-#U00a9NBC-150x150.jpg, Lucky-safeNBC-150x150.jpg)

Para OS X, GNU renomeação pode ser instalado usando homebrew : brew install rename.

KrisWebDev
fonte
Isso não funcionou na minha máquina (Arch Linux), mas a resposta de mik funcionou.
Marcvangend
@marcvangend Qual versão renamevocê está usando? # sudo pacman -S perl-renameinstalará a versão perl, que é mais poderosa e pode ser suficiente para fazer esta resposta funcionar para você.
John Gowers
@JohnGowers Thanks! Eu não sabia que existem duas versões. No meu sistema, rename --versionretorna rename from util-linux 2.29.2para que de fato não seja a versão perl.
Marcvangend 20/05
5
Existem dois renameutilitários comuns, mas nenhum deles é desenvolvido pelo GNU: As distribuições baseadas no Debian incluem um renameutilitário com seu pacote Perl, enquanto as distribuições baseadas no Red Hat usam o renameutilitário da util-linuxOrganização do Kernel do Linux. Seu link é para a funçãorename C da biblioteca padrão GNU.
Anthony G - justice for Monica
2
Nesta resposta, por que temos que escrever /gemrename 's/#U00a9/safe/g' *
Nikhil
21

encontre a lista de arquivos e substitua a palavra-chave. abaixo está um exemplo

find . -name '*jpg' -exec bash -c ' mv $0 ${0/\#U00a9NBC/safeNBC}' {} \;
Sujit Dhamale
fonte
11
Você precisa de aspas duplas em torno de seus mvargumentos, caso haja espaços no nome
Pare de prejudicar Monica
Eu precisava substituir todos os arquivos * _spec.rb para * _controller_spec.rb e sua solução funcionou para mim. Thanx.
jedi
18

Isso não é difícil, basta escapar do octothorpe (#) no nome, colocando uma barra invertida (\).

find . -type f -name 'Lucky-*' | while read FILE ; do
    newfile="$(echo ${FILE} |sed -e 's/\\#U00a9/safe/')" ;
    mv "${FILE}" "${newfile}" ;
done 
Comunidade
fonte
Sua explicação faz sentido, escapando dos #sons como o que eu preciso. Não vejo uma barra invertida no seu exemplo. Deve ficar assim: # s/\#U00a9/safe/
@LeonFrancisShelhamer good catch. Engoliu a barra invertida. Eu vou modificar.
17

Para escapar #do shell, use aspas simples ( '#'), aspas duplas ( "#") ou barra invertida ( \#).

O mais simples no seu caso seria usar o renamecomando (se estiver disponível):

rename '#U00a9' safe *.jpg
mik
fonte
2
Obrigado. Enquanto a resposta mais votada ( rename 's/#/somethingelse/' *) não funcionou na minha máquina (Arch Linux), esta funcionou.
marcvangend
11
Isso funciona usando o comando rename do util-linux.
imclean
10

não sabe como sed, mas você pode tentar isso em um shell bash:

for f in Lucky-#U00a9NBC-*.jpg; do mv -v "$f" "${f/#U00a9/safe}"; done;

explicação:

  1. percorre todos os nomes de arquivos correspondentes ao glob (Lucky- # U00a9NBC - *. jpg)
  2. renomeia o arquivo usando o comando move (mv)
  3. usa a substituição nativa do parâmetro bash $ {var / Pattern / Replacement} para criar o novo nome ("$ {f / # U00a9 / safe}")

Mais sobre a substituição de parâmetros (que é IMO altamente subutilizada): http://www.tldp.org/LDP/abs/html/parameter-substitution.html

Gregory Patmore
fonte
Embora esse código possa responder à pergunta, ele não é muito útil por si só. Explicar como resolve o problema melhoraria a utilidade e o valor a longo prazo da resposta.
Anthony G - justice para Monica
explicação passo a passo adicionada e leituras adicionais conforme o comentário de Anthony.
Gregory Patmore
1

Os exemplos acima não estavam funcionando no meu sistema (CentOS 5.6), então encontrei um comando (possivelmente mais específico do sistema) que funciona (nota: é necessário escapar de '#' \na linha de comando):

rename \#U00a9 safe *.jpg

[Também: ainda não tenho reputação suficiente para comentar, portanto, em resposta à pergunta de Nikhil sobre o uso de /gin rename 's/old_string/new_string/g'(apresentada nos comentários para outra resposta acima):

Use o gmodificador para executar uma substituição 'global' (ou seja, para substituir new_string por old_string quantas vezes ocorrer old_string). Isso não deve ser necessário na minha resposta, porque o renameserá aplicado a todos os arquivos especificados com *. Consulte https://www.computerhope.com/unix/rename.htm para obter uma explicação concisa deste e de outros modificadores.]

Ezra Citron
fonte
Corrigir; Os sistemas operacionais derivados do Fedora, como o CentOS, têm uma versão diferente dos renamesistemas operacionais derivados do Debian. Consulte unix.stackexchange.com/a/238862/135943 . E, a propósito, o CentOS 5.6 é bastante antigo e eu recomendo que você atualize.
Curinga
Ah, obrigado pela explicação + link. O sistema operacional desatualizado é no trabalho e por isso não depende de mim para atualizar :) mas um novo cluster está sendo construído e, presumivelmente, vamos atualizar quando passar ...
Ezra Citron
0

Aqui está a solução da DTK envolvida na função reutilizável do bash:

function renameFilesRecursively () {

  SEARCH_PATH="$1"
  SEARCH="$2"
  REPLACE="$3"

  find ${SEARCH_PATH} -type f -name "*${SEARCH}*" | while read FILENAME ; do
      NEW_FILENAME="$(echo ${FILENAME} | sed -e "s/${SEARCH}/${REPLACE}/g")";
      mv "${FILENAME}" "${NEW_FILENAME}";
  done

}

Veja como você pode usá-lo:

renameFilesRecursively /home/user/my-files apple orange
Slava Fomin II
fonte
0

Na verdade, renametem uma opção exatamente para aquela chamada --substou -sresumida. Não há necessidade de usar a sintaxe regex.

rename -s '#U00a9' 'safe' *

Se você deseja substituir / substituir várias ocorrências, use --subst-allou -S.

BTW, eu só queria substituir uma string por nada (remova-a do nome do arquivo) ... bem, também temos uma opção para ela -d/--deletee -D/--delete-all:

rename -d '#U00a9' *
lapin
fonte
-1

Outra opção é usar pyRenamer, um aplicativo criado especificamente para renomear em lote.

Pode ser instalado com sudo apt-get install pyrenamer

Para detalhes de uso, consulte o arquivo LEIA-ME no GitHub .

Sajna T
fonte
11
Se você realmente acha que isso poderia responder à pergunta, adicione algumas explicações à sua resposta. Por si só, instala apenas um pacote. Você deve explicar o que o comando faz e fornecer um exemplo que lide com os requisitos específicos do OP.
roaima 02/09