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

Ducky
fonte

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//:/-}.

sds
fonte
+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

noggerl
fonte
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
shupru
fonte
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
Dut A.
fonte
0

usando renamer :

$ renamer --find ":" --replace "-" *
Lloyd
fonte
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
0

Isso pode ser um exagero, mas você pode renomear qualquer caractere especial com o script no link fornecido nesta resposta:

/superuser//a/858671/365691

A.Danischewski
fonte