Como renomear arquivos com sed e csv

4

Sou novo no Linux, sed e awk , mas não me importo de me desafiar em novas ideias. Dito isso, eu entendo o propósito e como usar rename e sed para um evento comum, como adicionar um $date ou remover um _1234 de todos os arquivos. No entanto, quero descobrir como renomear 100 de arquivos que não têm relação um com o outro diferente do tipo de arquivo.

Exemplo de renomeação:

  • nome antigo alpha.ai renomeado para omega.ai
  • nome antigo pie32.ai renomeado para apple.ai
  • nome antigo xmas.ai renomeado para santa.ai

Eu usei originalmente um script bash para puxar todos os nomes para um arquivo .csv e colocá-los na coluna A. Na coluna B escrevi os novos nomes. Agora, como não há um evento comum ocorrendo, como você poderia escrever sed ou algo parecido para fazer isso?

#!/bin/bash
for i in *.ai
do
        mv $i $(echo $i | sed "a1,b1")

done
    
por DᴀʀᴛʜVᴀᴅᴇʀ 06.12.2012 / 17:35

4 respostas

6

Se você tiver um arquivo assim:

old_name1, new_name1
old_name2, new_name2
old_name3, new_name3

Você pode fazer um pequeno truque sujo:

sed 's/^/mv -vi "/;s/, /" "/;s/$/";/' < names.csv | bash -

O sed commnds (delimitado por ponto e vírgula) faz isso ( s é para substituto, / é usado como um delimitador, qualquer outro caractere faria, @ também é usado com frequência):

  • s/^/mv -vi "/ - adiciona mv -vi " no início de cada linha ( ^ é o início da linha);
  • s/, /" "/ - substitui a vírgula seguida por um espaço com " " ;
  • s/$/";/ - acrescenta aspas duplas a todas as linhas ( $ significa fim de linha)

e, portanto, a saída de sed será esta:

mv -vi "old_name1" "new_name1"
mv -vi "old_name2" "new_name2"
mv -vi "old_name3" "new_name3"

que será alimentado para bash para ser executado. As aspas em torno de nomes de arquivos não são obrigatórias, elas apenas guardam todos os espaços possíveis nos nomes dos arquivos (no entanto, elas não ajudarão contra espaços seguidos por uma vírgula, pois isso é usado como delimitador). o -v instrui mv a mostrar o que está fazendo (caso algo dê errado, você saberá o que aconteceu), -i fará com que ele pergunte se foi para sobrescrever o arquivo já existente.

    
por 06.12.2012 / 17:49
3

Existem vários problemas de cotação no seu script. Ele irá mangle nomes de arquivos contendo caracteres especiais: whitespace, \[?*- .

** Sempre use aspas duplas em torno das substituições de variáveis "$i" e substituições de comandos "$(sed …)". Sem aspas duplas, o valor da variável é interpretado como uma lista de padrões de caracteres universais separados por espaços em branco e cada padrão é substituído pela lista de nomes de arquivos correspondentes (se não houver correspondências, o padrão é deixado sozinho).

Além disso, se um nome de arquivo começar com - , ele será interpretado como uma opção por mv e possivelmente por echo . Passe -- primeiro para dizer ao comando que não haverá mais opções.

for i in *.ai; do
  mv -- "$i" "$(printf '%s\n' "$i" | sed 's,a1,b1,')"
done

(Isso ainda pressupõe que os nomes dos arquivos não contêm novas linhas.) (Eu também consertei o argumento sed no que você supostamente queria dizer.)

Se a sua lista de nomes de arquivos é simples, separada por vírgulas sem aspas, você pode analisá-los com um script de shell. Isso pressupõe que não haja vírgulas ou novas linhas em nenhum nome de arquivo.

while IFS=, read -r from to junk; do
  mv -- "$from" "$to"
done <"$files_to_rename.csv"

Se o seu arquivo de entrada for um arquivo CSV com cotação possível, use um analisador CSV real. Não tente fazer o seu próprio. Veja Existe uma ferramenta de linha de comando robusta? para processar arquivos csv? Por exemplo, em Python (com o CSV na entrada padrão):

import csv, os, sys
for line in csv.reader(sys.stdin):
    (source, dest) = line
    os.rename(source, dest)
    
por 07.12.2012 / 02:02
2

Se os seus arquivos tiverem caracteres engraçados ( ' , " , \ , $ ), você poderá percorrer o arquivo e lê-lo em uma matriz bash.

while IFS=, read -r -a arr; do mv "${arr[@]}"; done <files.csv 
    
por 06.12.2012 / 18:05
0

Quando me deparo com este tipo de problema, costumo usar o truque sed / bash à mão.

  1. Eu escrevo uma macro de editor ou um pequeno programa bobo que lê o arquivo csv e escreve linhas no formato 'mv arquivo1 arquivo2'.
  2. Em seguida, executo o script (ou macro) e salve a saída em run-my-cmds.sh
  3. Inspecionar run-my-cmds.sh visualmente para ter certeza de que vai para as coisas certas
  4. bash run-my-cmds.sh
por 06.12.2012 / 19:54