Encontre segunda instância de uma palavra em um arquivo e renomeie o arquivo

4

Eu arquivos que um sistema gera com um nome de arquivo genérico. Eu quero ter um script que eu possa executar que analisa esses arquivos para a segunda instância da palavra ProcID (após a palavra ProcID é um número) e, em seguida, renomeia o arquivo com o número ProcID. Atualmente tenho o seguinte:

FILEPATH; awk -F '[:)]' '/ProcID./{printf "mv %s %s.txt\n", FILENAME,  | "/bin/sh"; nextfile}' O*.TXT

Por exemplo, o script verifica arquivos e localiza a segunda instância de (ProcID:0000014778) e, em seguida, renomeia o arquivo com esse número de ID Proc.

O script acima encontra apenas a primeira instância e, portanto, os arquivos estão sendo renomeados antes de o sistema finalizar a saída para o arquivo.

    
por IanG 27.01.2017 / 16:58

2 respostas

5

O script abaixo renomeia todos os arquivos em um diretório, para o id na segunda string encontrada, começando com ProcID: :

1. Renomeando para o id na segunda string correspondente (literalmente; sem extensão)

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename if the second instance exists
        new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    except (IndexError, IsADirectoryError):
        pass
    else:
        # rename the file
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))

Para usar

  1. Copie o script em um arquivo vazio, salve-o como rename_files.py
  2. execute-o com o diretório como argumento:

    python3 /path/to/rename_files.py /path/to/directory_with_files
    

Notas

  • O script assume o formato (exato): ProcID:0000014778
  • O script não renomeia os arquivos se não houver uma segunda instância de ProcID (ou nenhum)

2. Renomeie apenas os arquivos .txt e mantenha a extensão

... Em seguida, use a versão abaixo, ela só renomeia .txt arquivos e mantém a extensão no arquivo renomeado. O uso é exatamente o mesmo.

#!/usr/bin/env python3
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename is the second instance exists
        new = [s for s in open(file).read().split() if all([
            s.startswith("(ProcID:"), f.endswith(".txt")
            ])][1]
    except (IndexError, IsADirectoryError):
        pass
    else:
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]+".txt"))

O que o script faz

  • lista os arquivos no diretório:

    for f in os.listdir(dr)
    
  • lista as strings dentro do arquivo, começando com ProcID:

    new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    

    O final [1] extrai a segunda ocorrência de strings, começando com ProcID: ( [0] é o primeiro)

  • divisões do id:

    new.split(":")[-1].strip()
    
  • e renomeia o arquivo, usando o id:

    shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))
    

EDITAR

Versão Python2 do script 1. O OP possui o python2 instalado, que requer IOError em vez de IsADirectoryError para evitar erros caso o script seja executado em um diretório em vez de um arquivo.

#!/usr/bin/env python
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename if the second instance exists
        new = [s for s in open(file).read().split() if s.startswith("(ProcID:")][1]
    except (IndexError, IOError):
        pass
    else:
        # rename the file
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()[:-1]))

... e por estar completo, uma versão python2 do segundo script:

#!/usr/bin/env python
import shutil
import os
import sys

dr = sys.argv[1]

for f in os.listdir(dr):
    file = os.path.join(dr, f)
    try:
        # only rename is the second instance exists
        new = [s for s in open(file).read().split() if all([
            s.startswith("(ProcID:"), f.endswith(".txt")
            ])][1]
    except (IndexError, IOError):
        pass
    else:
        shutil.move(file, os.path.join(dr, new.split(":")[-1].strip()+".txt"))
    
por Jacob Vlijm 27.01.2017 / 17:42
2

Seu script original estava perto, e pode ser editado para contar as instâncias via declaração if e uma variável de contador:

FILEPATH; awk -F '[:)]' '/ProcID./{ count++; if(count == 2 ){ printf "mv %s %s.txt\n", FILENAME,  | "/bin/sh"; nextfile}}' O*.TXT

Caso você esteja buscando uma solução alternativa, você pode usar este Perl script:

#!/usr/bin/env perl
use strict;
use warnings;

my $cnt=0;
open(my $fh,'<',$ARGV[0]) or die "open failed";
my $new_name;
while ( my $line = <$fh> ){
    $cnt+=1 if $line =~ /ProcID/;
    if($cnt==2){
        chomp $line;
        my @words = split(/[:)]/,$line); 
        $new_name = $words[1] . ".TXT";
        last;
    }
}
if (defined $new_name){
   rename $ARGV[0], $new_name;
}
close($fh)

Execução da amostra:

$ ls
0000014777.TXT  rename_by_procid.pl*

$ ./rename_by_procid.pl 0000014777.TXT                                                                                                

$ ls
0000014778.TXT  rename_by_procid.pl*
    
por Sergiy Kolodyazhnyy 27.01.2017 / 20:52