Renomeando pastas com base em um dicionário na forma de um arquivo CSV?

1

Vou descrever o problema bastante detalhado, já que aprendi que apenas falar sobre um subproblema específico que identifiquei leva a faltar a oportunidades ... Então, vou colocar um ponto inicial: Existe um conjunto de pastas que precisam ser renomeadas de acordo com um mapeamento em um arquivo CSV.

Os nomes das pastas seguem o seguinte padrão:

[[:alpha:]]*[[:digit:]]*_[[:alnum:]]*

Os dígitos no meio são relevantes e especificam o novo nome que a pasta deve ter. Então eu poderia executar o seguinte comando sed para extrair a parte do nome da pasta que me interessa.

sed 's/[[:alpha:]]*\([[:digit:]]*\)_[[:alnum:]]*//'

Portanto, podemos ter uma pasta chamada deptA100257_2bfde391c6af30fde3fca94b07bc8e7c e retirar o ID relevante 100257 . Depois, preciso renomear a pasta de acordo com o seguinte CSV:

63;9961
63;100257

O novo nome está à esquerda, o ID do nome antigo à direita. Portanto, a pasta do exemplo acima deve ser renomeada para 63 .

Primeiro problema óbvio: vários IDs podem mapear para um único nome. Eu resolveria isso criando todas as pastas "novas" na frente e copiando o conteúdo da pasta.

E eu poderia hackear isso usando Python ou qualquer outra coisa, possivelmente até mesmo alguns loops bash. Mas algo me diz que no núcleo, esta operação (substituição de acordo com um arquivo) não é exatamente incomum. Então, antes de reinventar a roda ...

Eu prefiro soluções usando shells e ferramentas * NIX padrão (especialmente bash ou zsh) e nenhuma linguagem "externa" como Perl, Ruby, Python ... Mas no final estou mais ou menos procurando uma abordagem "inteligente" e se houver uma boa linha Ruby que faça o trabalho, estou bem com isso.

    
por Marcus Riemer 04.01.2014 / 15:27

2 respostas

2

Eu usaria find para obter os nomes das pastas, analisá-los com sed , grep o ID correspondente e copiar o material:

$ find . -mindepth 1 -type d | while read dir; do 
   id=$(echo "$dir" | sed 's/\.\/[[:alpha:]]*\([[:digit:]]*\)_[[:alnum:]]*//'); 
   new_name=$(grep -w "$id" names.csv | cut -d ';' -f 1); 
   mkdir -p "$new_name" && mv -rv "$dir"/* "$new_name"/ && rmdir "$dir"; 
 done

Os truques são

  • use mkdir -p , que criará o diretório e sairá silenciosamente, se existir.
  • use grep -w no arquivo csv para obter apenas as linhas que contêm o ID inteiro limitado por caracteres não pertencentes à palavra. Dessa forma, você evita corresponder 1123 e 123 para o id 123 .
por 04.01.2014 / 16:14
1

Assumindo que seus diretórios estejam todos sob o diretório de trabalho atual, aqui está um ponto de partida (então testá-lo antes de executar no prod):

csvFile="/tmp/file.csv"

for d in ./*;
  # only work with directory
  [[ ! -d "$d" ] && continue

  # extract id from directory
  id="$(echo "$d" | sed 's/[[:alpha:]]*\([[:digit:]]*\)_[[:alnum:]]*//')"

  # fetch new name
  nid="$(awk -F';' '/'"$id"'/ {print $1}' "$csvFile")"

  # merge all matching dir into one
  mv "$d" "$nid"
done

Utilitários

Você viu:

  • mmv : mover em massa e renomear;
  • zmv : um módulo zsh que permite que as pessoas façam uma renomeação em massa.
por 04.01.2014 / 15:53

Tags