Renomeando Arquivo de Texto Usando Script

2

Eu tenho milhares de arquivos de texto dentro de uma pasta e eles são nomeados de uma certa maneira.

Por exemplo:

Image_234_Data_7778_n0.txt
Image_234_Data_7778_n1.txt
Image_234_Data_7778_n2.txt

Image_954_Data_4478_n0.txt
Image_954_Data_4478_n1.txt
Image_954_Data_4478_n2.txt

Image_104_Data_9878_n0.txt
Image_104_Data_9878_n1.txt
Image_104_Data_9878_n2.txt

E assim por diante ...

Eu gostaria de criar um arquivo fonte (que seria usado para renomear os arquivos e rastrear 'qual é qual') que deve ser lido:

1_1.txt:Image_234_Data_7778_n0.txt
1_2.txt:Image_234_Data_7778_n1.txt
1_3.txt:Image_234_Data_7778_n2.txt

2_1.txt:Image_954_Data_4478_n0.txt
2_2.txt:Image_954_Data_4478_n1.txt
2_3.txt:Image_954_Data_4478_n2.txt

3_1.txt:Image_104_Data_9878_n0.txt
3_2.txt:Image_104_Data_9878_n1.txt
3_3.txt:Image_104_Data_9878_n2.txt

E assim por diante ...

Alguém pode me ajudar com algum código que poderia fazer isso por mim?

    
por Tofayel 11.08.2014 / 15:03

3 respostas

1

Suponho que os nomes dos arquivos estejam no formato XXXXNNN.txt , em que XXXX é um texto arbitrário que não termina em um dígito e NNN é uma sequência de dígitos, e que você deseja agrupá-los por grupos de idênticos XXX.

Estratégia: faça o loop dos arquivos em ordem lexicográfica e detecte quando a parte XXXX é alterada. Para cada grupo, gere os novos nomes. Uma pequena complicação é que, se as partes NNN forem de largura variável, elas não serão classificadas de forma lexicográfica: NNN = 10 aparecerá entre NNN = 1 e NNN = 2.

current=
numbers=
i=0
for x in *.txt ''; do
  stem=${x%.*}
  n=${stem##*[!0-9]}
  stem=${stem%$n}
  if [ "$stem" != "$current" ]; then
    for k in $(printf '%s\n' $numbers | sort -n); do
      y=${i}_${k}.txt
      echo mv "$current$k.txt" "$y"
    done
    current=$stem
    numbers=$n
    i=$((i+1))
  else
    numbers="$numbers $n"
  fi
done

Substitua echo mv pelo comando que você deseja usar, por exemplo, mv para renomear os arquivos ou echo … para gravar informações em um arquivo.

Em vez de renomear arquivos e manter o controle dos nomes antigos, considere usar links simbólicos para que os arquivos sejam acessíveis como seus nomes originais e com os nomes simplificados.

    
por 12.08.2014 / 03:00
0

Depois de criar um diretório de teste contendo os seguintes arquivos:

Image_104_Data_9878_n0.txt, Image_104_Data_9878_n1.txt,
Image_234_Data_7778_n0.txt, Image_234_Data_7778_n1.txt,
Image_234_Data_7778_n2.txt, Image_954_Data_4478_n0.txt,
Image_954_Data_4478_n1.txt, Image_954_Data_4478_n2.txt

Eu então fiz:

printf %s\n * | sort --debug -t_ -k2,2n -k5.2n,5.2n 

E os resultados foram:

Image_104_Data_9878_n0.txt
      ___
                     _
__________________________
Image_104_Data_9878_n1.txt
      ___
                     _
__________________________
Image_234_Data_7778_n0.txt
      ___
                     _
__________________________
Image_234_Data_7778_n1.txt
      ___
                     _
__________________________
Image_234_Data_7778_n2.txt
      ___
                     _
__________________________
Image_954_Data_4478_n0.txt
      ___
                     _
__________________________
Image_954_Data_4478_n1.txt
      ___
                     _
__________________________
Image_954_Data_4478_n2.txt
      ___
                     _
__________________________

Eu disse sort para classificar primeiramente por número no campo delimitado por 2cd _ do início do campo ao final do campo como -k2,2n e secundariamente para classificar numericamente no segundo byte de 2cd no quinto campo como -k5.2,5.2n . Eu pedi por --debug de saída para me mostrar o que diabos estava fazendo.

Eu poderia ter classificado principalmente no 4º campo com facilidade, ou principalmente no campo 2, secundariamente no campo 5.2 e menos importante no segundo campo. Digo tudo isso porque não consigo determinar qualquer rima ou razão para o tipo oferecido em seu exemplo e só posso assumir que você os designou como:

  • 1_1: 234/7778
  • 2_1: 954/4478
  • 3_1: 104/9878

... porque você, até agora, não tem nenhum comando adequado para resolvê-los e talvez precise de um pequeno conselho sobre como fazê-lo. Seguindo essa suposição, farei o seguinte:

printf %s\n * | 
sort -t_ -k4,4n -k5.2n,5.2n | 
nl -bp'_n0\.' -s_ |
sed 's/\(I[^.]*_n\)\(.*\)/:/;N
     s/ *\([0-9]*_\)\(.*\n\) *\([^_]*I\)//;P;D'

Isso produz resultados que acredito que devem ser bem próximos do que você está procurando. Vêem?

1_0.txt:Image_954_Data_4478_n0.txt
1_1.txt:Image_954_Data_4478_n1.txt
1_2.txt:Image_954_Data_4478_n2.txt
2_0.txt:Image_234_Data_7778_n0.txt
2_1.txt:Image_234_Data_7778_n1.txt
2_2.txt:Image_234_Data_7778_n2.txt
3_0.txt:Image_104_Data_9878_n0.txt
3_1.txt:Image_104_Data_9878_n1.txt

Lá eles são classificados e numerados pelo quarto campo porque eu especifiquei o campo -k4,4n para sort , mas você poderia facilmente fazer o -k2,2n como indicado.

O comando funciona pedindo nl para numerar apenas as linhas que contêm a string _n0. . sed recebe sua saída, que se parece com:

 1_Image_954_Data_4478_n0.txt
   Image_954_Data_4478_n1.txt
   Image_954_Data_4478_n2.txt
 2_Image_234_Data_7778_n0.txt
   Image_234_Data_7778_n1.txt
   Image_234_Data_7778_n2.txt
 3_Image_104_Data_9878_n0.txt
   Image_104_Data_9878_n1.txt

... e primeiro copia o _n[0-9]*.txt bit para o início da linha, N ext puxa a próxima linha e, se o espaço padrão for semelhante:

 *num_.*\n [^_]*I

... nesse ponto, ele liga o numero da primeira linha ao segundo. Se você quisesse ir do arquivo de texto que o comando produziria para uma operação de movimentação, você poderia fazer:

sed 's/\([^:]*\):\(.*\)/$*  /' <txtfile |
sh -s -- echo mv

OUTPUT

mv Image_954_Data_4478_n0.txt 1_0.txt
mv Image_954_Data_4478_n1.txt 1_1.txt
mv Image_954_Data_4478_n2.txt 1_2.txt
mv Image_234_Data_7778_n0.txt 2_0.txt
mv Image_234_Data_7778_n1.txt 2_1.txt
mv Image_234_Data_7778_n2.txt 2_2.txt
mv Image_104_Data_9878_n0.txt 3_0.txt
mv Image_104_Data_9878_n1.txt 3_1.txt

Existe apenas echo ed porque esse é o primeiro parâmetro do processo do shell, mas se você removê-lo e executá-lo, como acabei de fazer, você vai gostar de obter os mesmos resultados:

ls -m

1_0.txt, 1_1.txt, 1_2.txt, 2_0.txt, 2_1.txt, 2_2.txt, 3_0.txt, 3_1.txt

Gilles recomenda links, o que eu também acho que é uma excelente ideia, embora eu pessoalmente evite softlinks se eu puder ajudar e apenas fazer um diretório de hardlink espelhado. Você poderia fazer isso quase da mesma maneira, mas você usaria ln em vez de mv .

    
por 12.08.2014 / 09:53
0

Um truque para coisas como essa - especialmente se você não for muito prático com scripts - é gerar um script com uma planilha. Isso não é uma boa prática se você estiver tentando criar um script para uso repetido, mas pode ser útil para um trabalho único para alguém que não teve tempo de aprender a fazer scripts de outra maneira.

Parece que a renomeação (ou link) que você está tentando realizar é alterar tudo antes do _n em um único número de sequência antes de um _ e deixar a parte após o _n inalterado. Se essa não é sua intenção exata, é fácil revisar uma fórmula de planilha.

Por exemplo (encurtando seus nomes de arquivos para reduzir a necessidade de rolar para o lado):

A2               B2             C2           D2           E2
i234d7778_n0.txt =FIND("_n",A2) =LEFT(A2,B2) =D1+(C2<>C1) =D2&"_"&RIGHT(A2,LEN(A2)-B2-1)
i234d7778_n0.txt 10             i234d7778_   1            1_0.txt

A razão pela qual isso começa na linha 2 (não 1) é para que a comparação em D2 vá para a linha 1. (Uma alternativa é colocá-lo na linha um, mas no caso especial D1 para 1.)

A expressão em D2 é apenas uma maneira sucinta de dizer isso: =IF(C2=C1,D1,D1+1)

Como de costume, com planilhas, cole sua lista de arquivos na coluna A e repita as colunas de B a E quantas vezes houver arquivos. Para gerar um script para fazer a renomeação, você pode adicionar uma coluna "F" ou "G":

F2                          G2
="mv "&A2&" "&E2            ="ln "&A2&" new-name-directory/"&E2
mv i234d7778_n0.tx 1_0.txt  ln i234d7778_n0.tx new-name-directory/1_0.txt

As colunas F e G fornecem o texto para um script executável.

    
por 12.09.2014 / 14:03