
Eu tenho uma lista de arquivos que desapareceram em algum lugar do nosso sistema de trabalho. Também tenho uma pasta cheia de 41 arquivos de log totalizando 46 MB que, esperançosamente, contêm entradas de log relacionadas aos arquivos ausentes. Como eu poderia usar esses arquivos de log para qualquer valor da minha lista?
A lista é estruturada como um arquivo por linha sem extensão de arquivo. Os logs parecem ter uma estrutura, mas ainda não estou totalmente familiarizado com essa estrutura. Ele contém nomes e caminhos de arquivos, bem como o que foi feito com ele.
Eu sei que posso cat *
todos os arquivos de log e canalizá-los para grep
. Provavelmente usarei -A
e -B
para obter um pouco de contexto dos arquivos de log quando um nome for encontrado. Estou usando o GnuWin32 no Windows para poder combinar isso com o Powershell, mas acho que isso exigiria que um nome de arquivo ocupasse todos os 46 MB e, quando eu passasse para o próximo nome de arquivo, eu recomeçasse. Tenho 1.830 arquivos na lista, portanto, se precisar começar do zero com cada um, acabarei lendo 46 MB tantas vezes que estarei lidando com GBs de dados repetidos. Parece ineficiente fazer assim.
Suponho que eu poderia construir um grande regex dos arquivos de 1830 ou juntá-los e executá-los uma vez nos logs, mas isso é viável? O regex teria quase 30 KB (1.830 arquivos * comprimento médio do nome do arquivo de cerca de 16 caracteres = 29.280 bytes, sem mencionar outros 1.830 bytes de símbolos de barra vertical).
Editar:Aqui está o que estou fazendo agora quando estou na pasta de logs e a lista está uma pasta atrás:
$logs = gc *
$notfound = gc ../notfound.txt
$logs | % { $i = 0; while ($i -lt $notfound.Count) { if ($_ -contains $notfound[$i]) { echo $_ }; $i++; } } | out-file C:\discovered.txt
É totalmente powershell. Estou disposto a usar qualquer ferramenta para acelerar isso porque no momento há 550.991 linhas em todos os arquivos de log combinados e há 1.830 nomes de arquivos, então essa abordagem está fazendo1.008.313.530 comparações. Está tudo na memória, então pelo menos não tenho E/S de disco me atrasando. Talvez eu consiga sair do caso while
se isso if
se tornar verdade, mas ainda farei tantas comparações que não tenho certeza se otimizar isso realmente fará algum bem. Já está funcionando há meia hora. Não há problema em reescrever minha abordagem da linha 1 se conseguir fazê-la antes de voltar para casa no fim de semana.
Responder1
Seria mais eficiente extrair os nomes dos arquivos dos logs por meio de uma expressão regular e ver se cada um deles está na sua lista. Poderia ser algo assim:
$notfound = gc ../notfound.txt
gc * |
select-string -AllMatches '\\(?<filename>[^\\]+)\.txt' |
select -ExpandProperty Matches |
% { $_.Groups['filename'].Value } |
? { $notfound -contains $_ } |
out-file C:\discovered.txt
Estou procurando arquivos parecidos com "\something.txt". Você terá que mudar isso.
Se ainda estiver muito lento e sua lista não encontrada for muito grande, talvez seja mais eficiente carregá-la em um HashSet .Net, mas eu não faria isso a menos que fosse necessário.