Como renomear arquivos e substituir caracteres?


11

Eu tenho um grupo de arquivos que possuem :(dois pontos) dentro do nome. Eu preciso substituir o :com -(traço).

Existe uma maneira fácil de fazer isso em um script?

FileName de amostra: 2013-10-11:11:52:08_055456663_045585_.txt

Respostas:


17

Um simples liner deve fazer (assume o shshell compatível com Posix ):

for f in *:*; do mv -v "$f" $(echo "$f" | tr ':' '-'); done

Explicação:

  • for ... in ...; do ...; doneé um loop

  • *:* corresponde a todos os arquivos e diretórios no diretório atual que possuem :seu nome

  • f é atribuído, por sua vez, a cada um desses nomes de arquivo no loop

  • mvrenomeia seu primeiro argumento para o segundo; -v(detalhado) pede que imprima o que faz; essa opção é específica do GNU-utils , portanto está disponível no Linux, mas não no Solaris

  • $(...) executa o código em um sub-shell e substitui a saída

  • echo imprime seu argumento na saída padrão

  • tr lê a saída padrão e converte os caracteres de acordo com o mapa fornecido

Se você estiver usando o bash , poderá evitar gerar um shell extra ( $()) com subprocessos ( tr) substituindo $(...)por ${f//:/-}.


+1 para uma resposta de trabalho simples, embora possa ser um pouco mais explicativa. Por exemplo, o for f inloop ... é um loop que itera sobre todos os arquivos no diretório atual em que os arquivos precisam corresponder *:*. (O que acontece com os dirs que correspondem?). O comando move é um movimento oldname newname em que o novo nome é gerado executando um shell com $( subshell here ). O que tr faz, ...
Hennes

@Hennes: este é superusuário - eu realmente preciso entrar nesses tipos de detalhes? Oh bem, aqui vai ...
sds

Não. Se houvesse uma necessidade real, eu não teria marcado com +1. E eu entendo o que faz. Eu acho que é bom para muitos outros leitores.
Hennes 14/10

2
Você pode substituir o $(echo "$f" | tr ':' '-')com "${f//:/-}"e evitar o subshell, canal e chamada de programa externa. Eu acho que isso é um basismo, mas eh. Veja aqui .
evilsoup

@evilsoup De fato; não faz muita diferença para pequenos conjuntos de dados (e um pode favorecer a legibilidade), mas você ficaria surpreso com a rapidez com que algo assim se soma. Eu fui mordido por isso recentemente; reescrever um script de modo que dois comandos simples de massagem de seqüência de caracteres não sejam mais necessários, reduzam facilmente o tempo de execução em 90% ou mais, o que em um grande conjunto de dados é convertido em vários minutos de tempo de execução do relógio de parede.
um CVn 15/10/2013

6

Conforme declarado em outro post por mim, a renameferramenta pode fazer o truque para você. Você só precisa digitar rename s/:/-/ <files to rename> Isso substitui todos os dois pontos por um traço em todos os arquivos que você nomear no final, ou seja,2013-10-*

Aqui está o link para o meu outro Post


1

Tenho certeza que um profissional UNIX poderia fazer isso com o bash, mas aqui está minha versão rápida e suja com o ruby.

path_to_files = "/home/username/wrongnames/"
filenames = `ls #{path_to_files}`.split
filenames.each do |fn|
  `mv #{path_to_files + fn} #{path_to_files + fn.gsub(/:/, "-")}`
end

defina path_to_files como o caminho para seus arquivos com nomes incorretos. salve o código acima em um arquivo chamado rename.rb e:

username@machinename$ ruby rename.rb

O @sds fornece uma resposta muito melhor. Devo excluir minha resposta? Eu sou novo no stackoverflow.
21713 shupru

1
Não; ainda tem valor significativo. :)
Blacklight Shining

2
No entanto, existem algumas desvantagens importantes com essa resposta que podem ser relevantes e que definitivamente valem a pena conhecer. (Pode ainda ser útil, mas ressalte o emptor e tudo mais.) Primeiramente, parece que ele se rompe muito quando encontra nomes de arquivos com espaço em branco (não apenas a nova linha clássica do caso de falha) neles. Além disso, mesmo que não fosse por espaço em branco, você deve citar o nome do arquivo na invocação do shell para proteger quaisquer outros caracteres especiais nos nomes dos arquivos do tratamento pelo shell (embora eu não saiba exatamente como o operador de backtick do Ruby funciona )
um CVn 15/10/2013

1

Se você tiver apenas um ou alguns arquivos, poderá renomear para você:

  1. Armazenar o padrão do nome do arquivo que você está alvejando como uma variável: p="201*".
  2. Armazenar o nome do arquivo de idade que deseja renomear: old_name=$(ls | grep $p).
  3. Armazene o novo nome de arquivo com as substituições de caracteres necessárias:

    new_name=$(ls | grep $p | sed 's/:/_/g')        # Using 'sed'
    
                OR
    
    new_name=$(ls | grep $p | tr ':' '_')           # Using 'tr'
    

Limpeza de bônus :
  a. Se, por uma questão de uniformidade, você deseja substituir os traços (-) pelos dois pontos (:) por sublinhados (_), você pode fazer o seguinte:

    new_name=$(ls | grep $p | tr ':-' '_');

  b. Se você quiser que o último sublinhado (logo antes do .txt) seja eliminado, defina a new_namevariável como:

    new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./')
  1. Agora renomeie seu arquivo conforme necessário: mv $old_name $new_name

         NB: mvfalhará se algum dos nomes de arquivo na operação de renomeação spacesestiver nele. Nesse caso, coloque as variáveis ​​apropriadas entre aspas, como:
mv "$old_name" $new_name OR mv $old_name "$new_name" OR mv "$old_name" "$new_name"


One-liners

1a: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | sed 's/:/_/g'); mv $old_name $new_name

1b: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':' '_'); mv $old_name $new_name

2: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_'); mv $old_name $new_name

3: p="201*"; old_name=$(ls | grep $p); new_name=$(ls | grep $p | tr ':-' '_' | sed 's/_\./\./'); mv $old_name $new_name

0

usando renamer :

$ renamer --find ":" --replace "-" *

Acho que instalar um ambiente node.js completo para renomear arquivos é um pouco demais. renameé uma ferramenta pré-instalada em muitas distribuições linux. Mas acho que para o Windows essa ferramenta pode ser ótima.
noggerl

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.