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

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

Eu sou novo no ecossistema do Windows. Recebi a tarefa de escrever um programa que pesquisará várias dezenas (talvez até centenas) de milhares de arquivos em busca de uma string específica. A string que deve ser correspondida é um número de série que consiste apenas em números e letras e tem menos de 20 caracteres. Neste momento, meu programa está executando o seguinte comando:

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

O comando acima funciona, porém é muito lento. Os arquivos que podem conter um número de série específico terão apenas o número de série na primeira linha.

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

Responder1

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-ChildItemsubpastas recursivas, etc; para Get-Contentpoder obter mais ou menos conteúdo do arquivo; e Select-Stringpode realizar correspondências mais complexas (regex, distinção entre maiúsculas e minúsculas, etc.).

Responder2

Posso sugerir algumas opções se você não precisar usar o findstr, mas antes de tudo você deve verificar se pode restringir a pesquisa a arquivos de um determinado tipo de arquivo, pois isso certamente agilizará as coisas.

  1. Localizador de arquivos LiteNa minha experiência, é mais rápido 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":AGfoi desenvolvido para ser rápido, portanto, deve fornecer resultados rapidamente. Certifique-se de restringir a pesquisa por tipo de arquivo, se puder, embora os arquivos binários já sejam ignorados por padrão. Também disponível emCygwin.

  3. find -exec awk 'BEGIN {IGNORECASE=1} NR==1 && /searchStr/ {print FILENAME": "$0}' {} \;Tente fazer isso se você tiver o Cygwin ou outro ambiente semelhante ao POSIX disponível, para verificar sua ideia de pesquisar apenas a primeira linha. Combine findpara obter os nomes dos arquivos (e também filtrá-los) e awkpara verificar a primeira linha e imprimi-la junto com o nome do arquivo.
  4. find | parallel 'perl -lane '\'' print "$ARGV: $_" if $. == 1 and /searchStr/i '\'' {}'Outra ideia para tentar agilizar as coisas é colocar núcleos e threads disponíveis para funcionar: é isso queParalelo GNUé para. Este exemplo é esportivo perl, mas faz o mesmo que awkacima 3.. Aqui está um detalhamento do comando:

    findprocure arquivos no diretório atual e 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", ou seja, alimentar a lista de resultados para o próximo comando.

    parallelexecute o próximo comando em paralelo.

    perllinguagem de script que se destaca na manipulação de arquivos de texto, pode substituir sedou awk.

    -laneconjunto útil de opções para perl one-liners.

    '\''apóstrofo escapado, necessário porque já abrimos um apóstrofo definido depois de parallel.

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

    ifexecute a instrução anterior apenas se as seguintes condições forem atendidas.

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

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

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

    '\''outro apóstrofo escapado marca o fim da perlinstrução.

    {}this será substituído por parallelcada um dos nomes de arquivos transmitidos por find.

    'final da parallelinstrução.

Atualizar:Ambos awke perlleem 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 '\'' {}'

informação relacionada