Comando mais eficiente para pesquisar a primeira linha de muitos arquivos (windows)

1

Eu sou novo no ecossistema do Windows. Eu fui encarregado de escrever um programa que irá pesquisar vários 10 (talvez até 100) de milhares de arquivos para uma string específica. A string que deve ser correspondida é um número de série que consiste em apenas números e letras e é menor que 20 caracteres. No momento, meu programa está executando o seguinte comando:

findstr /i /m /s "searchStr" "C:\Directory\To\Search\*.*"

O comando acima funciona, no entanto, é muito lento. O (s) arquivo (s) que podem conter um número de série específico terão apenas o número de série em sua primeira linha.

Alguém sabe de uma maneira eficiente de pesquisar recursivamente um diretório para todos os arquivos que contêm uma string específica somente na primeira linha?

    
por tpdietz 09.06.2015 / 17:33

2 respostas

2

No PowerShell (v3.0 +), talvez ...

Get-ChildItem -Path x:\pathto\*.log '
| ForEach-Object {
    if (Get-Content -LiteralPath $_ -First 1 '
        | Select-String -SimpleMatch -Pattern 'serialnumber') 
    {
        Write-Output $_
    }
}

Parâmetros diferentes para Get-ChildItem podem recriar subpastas, etc; para Get-Content pode obter mais ou menos conteúdo do arquivo; e para Select-String pode realizar correspondências mais complexas (regex, diferencia maiúsculas de minúsculas, etc.).

    
por 16.05.2017 / 14:53
1

Eu posso sugerir algumas opções se você não precisa usar findstr , mas antes de tudo você deve ver se você pode restringir a busca a arquivos de um certo tipo de arquivo, pois isso certamente irá acelerar as coisas.

  1. O FileLocator Lite está na minha experiência mais rápido em encontrar arquivos e verificar seu conteúdo. Certifique-se de preencher os campos "nome do arquivo" (se aplicável) e "texto contido", bem como o diretório inicial.

  2. ag -il "searchStr" : ag é construído para velocidade deve dar resultados, rápido. Não se esqueça de restringir a pesquisa por tipo de arquivo, se possível, embora os arquivos binários já sejam ignorados por padrão. Também disponível em Cygwin .

  3. find -exec awk 'BEGIN {IGNORECASE=1} NR==1 && /searchStr/ {print FILENAME": "$0}' {} \; Tente isso se você tiver o Cygwin ou outro ambiente semelhante ao POSIX disponível, a fim de verificar sua ideia de pesquisar apenas a primeira linha. Combine find para obter os nomes dos arquivos (e esperamos que também os filtre) e awk para verificar a primeira linha e imprimi-los junto com o nome do arquivo.
  4. find | parallel 'perl -lane '\'' print "$ARGV: $_" if $. == 1 and /searchStr/i '\'' {}' Outra ideia para tentar acelerar as coisas é colocar cores e threads disponíveis para funcionar: é isso que GNU é paralelo é para. Este exemplo exibe perl , mas faz o mesmo que awk em 3. acima. Aqui está uma lista de comandos:

    find procura arquivos no diretório atual e em seus subdiretórios. Você pode especificar um diretório diferente para procurar e um padrão ou extensão de arquivo para filtrar: find /cygdrive/c/Directory/To/Search -iname "*.txt" .

    | "pipe", isto é, alimente a lista de resultados para o próximo comando.

    parallel executa o próximo comando em paralelo.

    perl linguagem de script que se destaca na manipulação de arquivos de texto, pode substituir sed ou awk .

    -lane conjunto útil de switches para perl one-liners.

    '\'' de apóstrofo com escape, necessário, pois já abrimos um apóstrofo definido após parallel .

    print "$ARGV: $_" imprime o nome do arquivo ( $ARGV ), dois pontos, um espaço e a linha completa ( $_ ).

    if somente executa a instrução anterior se as seguintes condições forem atendidas.

    $. == 1 número da linha ( $. ) é igual a um ( 1 ), ou seja, estamos vendo a primeira linha do arquivo.

    and a seguinte condição também deve ser atendida.

    /searchStr/i a linha que está sendo examinada contém o texto searchStr , sem distinção entre maiúsculas e minúsculas.

    '\'' outro apóstrofo com escape marca o fim da instrução perl .

    {} isto será substituído por parallel com cada um dos nomes de arquivos passados por find .

    ' end da instrução parallel .

Atualização: Tanto awk como perl leem o arquivo inteiro, mesmo que as ações estejam vinculadas apenas à primeira linha. A solução é parar explicitamente a elaboração na linha 2:

find -exec awk 'BEGIN {IGNORECASE=1} NR > 1 {exit} /searchStr/ {print FILENAME": "$0}' {} \; find | parallel 'perl -lape '\'' exit if $. == 2; print "$ARGV: $_" if /searchStr/i '\'' {}'

    
por 16.05.2017 / 16:50