Quais são os recursos e limitações não documentados do comando FINDSTR do Windows?


188

O comando FINDSTR do Windows está terrivelmente documentado. Existe uma ajuda muito básica da linha de comando disponível em FINDSTR /?, ou HELP FINDSTR, mas é lamentavelmente inadequada. Há um pouco mais de documentação online em https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Existem muitos recursos e limitações do FINDSTR que nem são mencionados na documentação. Nem poderiam ser antecipados sem conhecimento prévio e / ou experimentação cuidadosa.

Portanto, a pergunta é: quais são os recursos e limitações não documentadas do FINDSTR?

O objetivo desta pergunta é fornecer um repositório único dos muitos recursos não documentados para que:

A) Os desenvolvedores podem aproveitar ao máximo os recursos existentes.

B) Os desenvolvedores não perdem tempo se perguntando por que algo não funciona quando parece que deveria.

Certifique-se de conhecer a documentação existente antes de responder. Se as informações são cobertas pela AJUDA, elas não pertencem aqui.

Este também não é um lugar para mostrar usos interessantes do FINDSTR. Se uma pessoa lógica puder antecipar o comportamento de um uso específico do FINDSTR com base na documentação, ele não pertence aqui.

Na mesma linha, se uma pessoa lógica poderia antecipar o comportamento de um uso específico com base nas informações contidas em qualquer resposta existente, então, novamente, ele não pertence aqui.


15
Ou, como alternativa, você pode abandonar completamente o utilitário MS não documentado de baixa qualidade e instalar / usar, grepque é muito bem entendido e documentado :-) Veja stackoverflow.com/questions/2635740/… por exemplo.
22412

17
Por todos os meios, se você estiver em posição de usar algo diferente do FINDSTR, isso é altamente recomendável. Mas algumas pessoas estão em ambientes onde os utilitários de terceiros são proibidos.
dbenham

4
Nenhuma ofensa tomada. Eu considerei seriamente colocar em meu próprio aviso de isenção de responsabilidade do FINDSTR semelhante ao seu comentário! :)
dbenham

41
Estou chocado e desapontado que alguém ache esta pergunta "Não Construtiva" e vote para encerrar. Muita reflexão foi colocada na questão especificamente para evitar "opiniões, debates, argumentos, pesquisas ou discussões prolongadas". A pergunta foi publicada por 3,5 meses e nenhum dos negativos citados ocorreu. A resposta combinada está cheia de fatos e exigiu muitas horas de pesquisa e experimentação meticulosas.
Dbenham 30/04

6
Alguns leitores podem estar interessado no contexto histórico do comando findstr: blogs.msdn.com/b/oldnewthing/archive/2012/11/28/10372436.aspx
Harry Johnston

Respostas:


279

Prefácio
Muitas das informações nesta resposta foram coletadas com base em experimentos executados em uma máquina Vista. Salvo indicação explícita em contrário, não confirmei se as informações se aplicam a outras versões do Windows.

Saída FINDSTR
A documentação nunca se preocupa em explicar a saída do FINDSTR. Alude ao fato de que linhas correspondentes são impressas, mas nada mais.

O formato da saída de linha correspondente é o seguinte:

filename: lineNumber: lineOffset: text

Onde

fileName: = O nome do arquivo que contém a linha correspondente. O nome do arquivo não será impresso se a solicitação for explicitamente para um único arquivo ou se estiver pesquisando entrada canalizada ou redirecionada. Quando impresso, o nome do arquivo sempre inclui todas as informações de caminho fornecidas. Informações adicionais sobre o caminho serão adicionadas se a/Sopção for usada. O caminho impresso é sempre relativo ao caminho fornecido ou ao diretório atual, se nenhum for fornecido.

Nota - O prefixo do nome do arquivo pode ser evitado ao pesquisar vários arquivos usando os curingas não padrão (e mal documentados) < e >. As regras exatas de como esses curingas funcionam podem ser encontradas aqui . Por fim, você pode ver este exemplo de como os curingas não padrão funcionam com o FINDSTR .

lineNumber: = O número da linha da linha correspondente representada como um valor decimal com 1 representando a 1ª linha da entrada. Impresso apenas se a/Nopção for especificada.

lineOffset: = O deslocamento de bytes decimais do início da linha correspondente, com 0 representando o 1º caractere da 1ª linha. Impresso apenas se a/Oopção for especificada. Este não éo deslocamento da partida dentro da linha. É o número de bytes desde o início do arquivo até o início da linha.

text = A representação binária da linha correspondente, incluindo qualquer <CR> e / ou <LF>. Nada é deixado de fora da saída binária, de modo que este exemplo que corresponda a todas as linhas produza uma cópia binária exata do arquivo original.

FINDSTR "^" FILE >FILE_COPY

A opção / A define a cor do fileName :, lineNumber: e lineOffset: somente saída. O texto da linha correspondente é sempre impresso com a cor atual do console. A opção / A somente tem efeito quando a saída é exibida diretamente no console. A opção / A não terá efeito se a saída for redirecionada para um arquivo ou canalizada. Veja a edição 2018-08-18 na resposta de Aacini para obter uma descrição do comportamento do buggy quando a saída é redirecionada para CON.

A maioria dos caracteres de controle e muitos caracteres ASCII estendidos são exibidos como pontos no XP O
FINDSTR no XP exibe a maioria dos caracteres de controle não imprimíveis das linhas correspondentes como pontos (pontos) na tela. Os seguintes caracteres de controle são exceções; eles são exibidos como eles mesmos: Guia 0x09, Alimentação de linha 0x0A, Guia vertical 0x0B, Alimentação de formulário 0x0C, Retorno de carro 0x0D.

O XP FINDSTR também converte vários caracteres ASCII estendidos em pontos também. Os caracteres ASCII estendidos que são exibidos como pontos no XP são os mesmos que são transformados quando fornecidos na linha de comando. Consulte a seção "Limites de caracteres para parâmetros de linha de comando - transformação ASCII estendida" , posteriormente nesta postagem

Caracteres de controle e ASCII estendido não serão convertidos em pontos no XP se a saída for canalizada, redirecionada para um arquivo ou dentro de uma cláusula FOR IN ().

O Vista e o Windows 7 sempre exibem todos os caracteres como eles mesmos, nunca como pontos.

Códigos de retorno (ERRORLEVEL)

  • 0 (sucesso)
    • A correspondência foi encontrada em pelo menos uma linha de pelo menos um arquivo.
  • 1 (falha)
    • Não foi encontrada nenhuma correspondência em nenhuma linha de nenhum arquivo.
    • Cor inválida especificada pela /A:xxopção
  • 2 (erro)
    • Opções incompatíveis /Le /Rambas especificadas
    • Faltando argumento após /A:, /F:, /C:, /D:, ou/G:
    • Arquivo especificado por /F:fileou /G:filenão encontrado
  • 255 (erro)

Origem dos dados a serem pesquisados (atualizado com base nos testes com o Windows 7) O
Findstr pode pesquisar dados de apenas uma das seguintes fontes:

  • nomes de arquivos especificados como argumentos e / ou usando a /F:fileopção

  • stdin via redirecionamento findstr "searchString" <file

  • fluxo de dados de um tubo type file | findstr "searchString"

Argumentos / opções têm precedência sobre o redirecionamento, que tem precedência sobre dados canalizados.

Argumentos de nome de arquivo e /F:filepodem ser combinados. Vários argumentos de nome de arquivo podem ser usados. Se várias /F:fileopções forem especificadas, somente a última será usada. Curingas são permitidos nos argumentos do nome do arquivo, mas não no arquivo apontado por /F:file.

Origem das strings de pesquisa (atualizadas com base em testes com o Windows 7)
As opções /G:filee /C:stringpodem ser combinadas. Várias /C:stringopções podem ser especificadas. Se várias /G:fileopções forem especificadas, somente a última será usada. Se um /G:fileou /C:stringfor usado, todos os argumentos que não sejam de opção serão considerados arquivos a serem pesquisados. Se nem /G:filenem /C:stringfor usado, o primeiro argumento não opcional será tratado como uma lista delimitada por espaço de termos de pesquisa.

Os nomes de arquivos não devem ser citados no arquivo ao usar a /F:FILEopção
Os nomes de arquivos podem conter espaços e outros caracteres especiais. A maioria dos comandos exige que esses nomes de arquivos sejam citados. Mas a /F:files.txtopção FINDSTR exige que os nomes de arquivos em files.txt NÃO sejam citados. O arquivo não será encontrado se o nome estiver entre aspas.

BUG - Short nomes de arquivo 8.3 pode quebrar o /De /Sopções
Tal como acontece com todos os comandos do Windows, FINDSTR tentará coincidir com o nome longo e curto 8.3 nome quando se olha para os arquivos a serem pesquisados. Suponha que a pasta atual contenha os seguintes arquivos não vazios:

b1.txt
b.txt2
c.txt

O comando a seguir encontrará com êxito todos os 3 arquivos:

findstr /m "^" *.txt

b.txt2corresponde porque o nome abreviado correspondente B9F64~1.TXTcorresponde. Isso é consistente com o comportamento de todos os outros comandos do Windows.

Mas um erro com as opções /De /Sfaz com que os seguintes comandos encontrem apenasb1.txt

findstr /m /d:. "^" *.txt
findstr /m /s "^" *.txt

O erro evita que b.txt2seja encontrado, assim como todos os nomes de arquivos que são classificados b.txt2no mesmo diretório. Arquivos adicionais que são classificados antes, como a.txt, são encontrados. Arquivos adicionais que são classificados mais tarde, como d.txt, são perdidos quando o bug foi acionado.

Cada diretório pesquisado é tratado de forma independente. Por exemplo, a /Sopção começaria a pesquisar com êxito em uma pasta filha após não encontrar os arquivos no pai, mas assim que o bug fizer com que um nome de arquivo curto seja perdido no filho, todos os arquivos subsequentes nessa pasta filho também serão perdidos .

Os comandos funcionam sem erros se os mesmos nomes de arquivo forem criados em uma máquina com a geração de nomes NTFS 8.3 desativada. Claro b.txt2que não seria encontrado, mas c.txtseria encontrado corretamente.

Nem todos os nomes abreviados acionam o bug. Todas as instâncias de comportamento que vi envolvem uma extensão com mais de 3 caracteres com um nome 8.3 curto que começa da mesma forma que um nome normal que não requer um nome 8.3.

O bug foi confirmado no XP, Vista e Windows 7.

Caracteres não imprimíveis e a /Popção
A /Popção faz com que o FINDSTR ignore qualquer arquivo que contenha qualquer um dos seguintes códigos de bytes decimais:
0-7, 14-25, 27-31.

Em outras palavras, a /Popção ignorará apenas arquivos que contenham caracteres de controle não imprimíveis. Os caracteres de controle são códigos menores ou iguais a 31 (0x1F). O FINDSTR trata os seguintes caracteres de controle como imprimíveis:

 8  0x08  backspace
 9  0x09  horizontal tab
10  0x0A  line feed
11  0x0B  vertical tab
12  0x0C  form feed
13  0x0D  carriage return
26  0x1A  substitute (end of text)

Todos os outros caracteres de controle são tratados como não imprimíveis, cuja presença faz com que a /Popção ignore o arquivo.

A entrada canalizada e redirecionada pode ter sido <CR><LF>anexada
Se a entrada for canalizada e o último caractere do fluxo não for <LF>, o FINDSTR será automaticamente anexado <CR><LF>à entrada. Isso foi confirmado no XP, Vista e Windows 7. (Eu costumava pensar que o canal do Windows era responsável por modificar a entrada, mas descobri que o FINDSTR está realmente fazendo a modificação).

O mesmo vale para a entrada redirecionada no Vista. Se o último caractere de um arquivo usado como entrada redirecionada não for <LF>, o FINDSTR será anexado automaticamente <CR><LF>à entrada. No entanto, XP e Windows 7 não alteram a entrada redirecionada.

O FINDSTR trava no XP e no Windows 7 se a entrada redirecionada não terminar com<LF>
Esse é um "recurso" desagradável no XP e no Windows 7. Se o último caractere de um arquivo usado como entrada redirecionada não terminar <LF>, o FINDSTR travará indefinidamente assim que atinge o final do arquivo redirecionado.

A última linha de dados canalizados pode ser ignorada se consistir em um único caractere.
Se a entrada é canalizada e a última linha consiste em um único caractere que não é seguido por <LF>, o FINDSTR ignora completamente a última linha.

Exemplo - O primeiro comando com um único caractere e sem <LF>falha na correspondência, mas o segundo comando com 2 caracteres funciona bem, assim como o terceiro comando que possui um caractere com o término da nova linha.

> set /p "=x" <nul | findstr "^"

> set /p "=xx" <nul | findstr "^"
xx

> echo x| findstr "^"
x

Relatado pelo usuário do DosTips Sponge Belly no novo bug do findstr . Confirmado no XP, Windows 7 e Windows 8. Ainda não ouviu falar do Vista. (Eu não tenho mais o Vista para testar).

Sintaxe da opção As
opções podem ser prefixadas com /ou - Opções podem ser concatenadas após um único /ou -. No entanto, a lista de opções concatenadas pode conter no máximo uma opção de vários caracteres, como OFF ou F:, e a opção de vários caracteres deve ser a última opção da lista.

A seguir, são apresentadas todas as formas equivalentes de expressar uma regex sem distinção entre maiúsculas e minúsculas, procurando por qualquer linha que contenha "olá" e "adeus" em qualquer ordem

  • /i /r /c:"hello.*goodbye" /c:"goodbye.*hello"

  • -i -r -c:"hello.*goodbye" /c:"goodbye.*hello"

  • /irc:"hello.*goodbye" /c:"goodbye.*hello"

Limites de comprimento da string de pesquisa
No Vista, o comprimento máximo permitido para uma única string de pesquisa é de 511 bytes. Se qualquer sequência de pesquisa exceder 511, o resultado será um FINDSTR: Search string too long.erro no ERRORLEVEL 2.

Ao fazer uma pesquisa de expressão regular, o comprimento máximo da string de pesquisa é 254. Uma expressão regular com comprimento entre 255 e 511 resultará em um FINDSTR: Out of memoryerro com ERRORLEVEL 2. Um comprimento de expressão regular> 511 resulta no FINDSTR: Search string too long.erro.

No Windows XP, o comprimento da string de pesquisa é aparentemente menor. Erro Findstr: "A cadeia de pesquisa é muito longa": como extrair e corresponder a substring no loop "for"? O limite do XP é de 127 bytes para pesquisas literais e regex.

Limites de comprimento de linha Os
arquivos especificados como argumento de linha de comando ou através da opção / F: FILE não possuem limite de comprimento de linha conhecido. As pesquisas foram executadas com êxito em um arquivo de 128 MB que não continha um único <LF>.

Dados canalizados e entrada redirecionada são limitados a 8191 bytes por linha. Esse limite é um "recurso" do FINDSTR. Não é inerente a pipes ou redirecionamentos. O FINDSTR usando stdin redirecionado ou entrada canalizada nunca corresponderá a nenhuma linha que seja> = 8k bytes. Linhas> = 8k geram uma mensagem de erro para stderr, mas ERRORLEVEL ainda é 0 se a cadeia de pesquisa for encontrada em pelo menos uma linha de pelo menos um arquivo.

Tipo de pesquisa padrão: Literal vs Expressão regular
/C:"string" - O padrão é / L literal. Combinar explicitamente a opção / L com / C: "string" certamente funciona, mas é redundante.

"string argument"- O padrão depende do conteúdo da primeira cadeia de pesquisa. (Lembre-se de que <espaço> é usado para delimitar cadeias de caracteres de pesquisa.) Se a primeira cadeia de caracteres de pesquisa for uma expressão regular válida que contenha pelo menos um meta-caractere não escapado, todas as cadeias de caracteres de pesquisa serão tratadas como expressões regulares. Caso contrário, todas as cadeias de pesquisa serão tratadas como literais. Por exemplo, "51.4 200"será tratado como duas expressões regulares porque a primeira string contém um ponto não escapado, enquanto "200 51.4"será tratado como dois literais porque a primeira string não contém meta-caracteres.

/G:file- O padrão depende do conteúdo da primeira linha não vazia no arquivo. Se a primeira cadeia de pesquisa for uma expressão regular válida que contenha pelo menos um meta-caractere não escapado, todas as cadeias de pesquisa serão tratadas como expressões regulares. Caso contrário, todas as cadeias de pesquisa serão tratadas como literais.

Recomendação - Sempre especifique explicitamente /La opção literal ou /Ra expressão regular ao usar "string argument"ou /G:file.

Erro - especificar várias seqüências de pesquisa literais pode gerar resultados não confiáveis

O exemplo simples a seguir de FINDSTR falha ao encontrar uma correspondência, mesmo que deva.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Este bug foi confirmado no Windows Server 2003, Windows XP, Vista e Windows 7.

Com base em experimentos, o FINDSTR pode falhar se todas as seguintes condições forem atendidas:

  • A pesquisa está usando várias cadeias de pesquisa literais
  • As cadeias de pesquisa têm diferentes comprimentos
  • Uma cadeia de pesquisa curta possui uma certa quantidade de sobreposição com uma cadeia de pesquisa mais longa
  • A pesquisa diferencia maiúsculas de minúsculas (sem /Iopção)

Em todas as falhas que eu vi, é sempre uma das seqüências de pesquisa mais curtas que falha.

Para obter mais informações, consulte Por que esse exemplo do FINDSTR com várias seqüências de pesquisa literais não encontra uma correspondência?

Citações e retrocessos nos argumentos da linha de comando
Nota - Os comentários do usuário MC ND refletem as regras realmente terrivelmente complicadas para esta seção. Existem três fases de análise distintas envolvidas:

  • O primeiro cmd.exe pode exigir que algumas aspas sejam escapadas como ^ "(realmente nada a ver com FINDSTR)
  • O próximo FINDSTR usa o analisador de argumentos anterior ao MS C / C ++ 2008 , que possui regras especiais para "e \
  • Depois que o analisador de argumentos termina, o FINDSTR trata adicionalmente \ seguido por um caractere alfanumérico como literal, mas \ seguido por um caractere não alfanumérico como caractere de escape

O restante desta seção destacada não está 100% correto. Pode servir como um guia para muitas situações, mas as regras acima são necessárias para o entendimento total.

Escapando Citação nas cadeias de pesquisa da linha de comando As
cotas nas cadeias de pesquisa da linha de comando devem ser escapadas com uma barra invertida \". Isso é verdade para as cadeias de pesquisa literal e regex. Esta informação foi confirmada no XP, Vista e Windows 7.

Nota: A cotação também pode precisar ser escapada para o analisador CMD.EXE, mas isso não tem nada a ver com FINDSTR. Por exemplo, para procurar uma única citação, você pode usar:

FINDSTR \^" file && echo found || echo not found

Escapando a barra invertida nas cadeias de pesquisa literais da linha de comando A
barra invertida em uma cadeia de pesquisa literal pode normalmente ser representada como \ou como \\. Eles são tipicamente equivalentes. (Pode haver casos incomuns no Vista em que a barra invertida sempre deve ser escapada, mas eu não tenho mais uma máquina do Vista para testar) .

Mas existem alguns casos especiais:

Ao procurar barras invertidas consecutivas, todas, exceto a última, devem ser escapadas. A última barra invertida pode opcionalmente ser escapada.

  • \\pode ser codificado como \\\ou\\\\
  • \\\pode ser codificado como \\\\\ou\\\\\\

A pesquisa de uma ou mais barras invertidas antes de uma cotação é bizarra. A lógica sugere que a cotação deve ser escapada, e cada uma das barras invertidas principais precisaria ser escapada, mas isso não funciona! Em vez disso, cada uma das barras invertidas principais deve ter escape duplo e a citação é escapada normalmente:

  • \" deve ser codificado como \\\\\"
  • \\" deve ser codificado como \\\\\\\\\"

Como observado anteriormente, uma ou mais cotações de escape também podem exigir escape ^para o analisador de CMD

As informações nesta seção foram confirmadas no XP e Windows 7.

Escapando barra invertida nas cadeias de pesquisa de expressão regular da linha de comandos

  • Apenas Vista: a barra invertida em uma regex deve ter escape duplo como \\\\, ou escape único em uma classe de caracteres definida como [\\]

  • XP e Windows 7: a barra invertida em uma regex sempre pode ser representada como [\\]. Normalmente pode ser representado como \\. Mas isso nunca funciona se a barra invertida preceder uma cotação de escape.

    Uma ou mais barras invertidas antes de uma cotação de escape devem ser de escape duplo ou codificadas como [\\]

    • \"pode ser codificado como \\\\\"ou[\\]\"
    • \\"pode ser codificado como \\\\\\\\\"ou [\\][\\]\"ou\\[\\]\"

Escapando
aspas e barra invertida em cadeias de pesquisa literais / G: FILE As aspas e barras invertidas independentes em um arquivo de cadeia de pesquisa literal especificado por / G: file não precisam ser escapadas, mas podem ser.

"e \"são equivalentes.

\e \\são equivalentes.

Se a intenção é encontrar \\, pelo menos a barra invertida principal deve ser escapada. Ambos \\\e \\\\trabalho.

Se a intenção é encontrar \ ", pelo menos a barra invertida principal deve ser escapada. Ambos \\"e \\\"funcionam.

Citação de
escape e barra invertida em / G: FILE seqüências de pesquisa de regex Esse é o caso em que as seqüências de escape funcionam conforme o esperado com base na documentação. Quote não é um metacaractere regex, portanto, não precisa ser escapado (mas pode ser). A barra invertida é um metacaractere de expressão regular, portanto deve ser escapada.

Limites de caracteres para parâmetros da linha de comandos - transformação ASCII estendida
O caractere nulo (0x00) não pode aparecer em nenhuma sequência na linha de comandos. Qualquer outro caractere de byte único pode aparecer na sequência (0x01 - 0xFF). No entanto, o FINDSTR converte muitos caracteres ASCII estendidos encontrados nos parâmetros da linha de comando em outros caracteres. Isso tem um grande impacto de duas maneiras:

1) Muitos caracteres ASCII estendidos não corresponderão se forem usados ​​como uma sequência de pesquisa na linha de comando. Essa limitação é a mesma para pesquisas literais e regex. Se uma sequência de pesquisa precisar conter ASCII estendido, o comando/G:FILE opção deverá ser usada.

2) O FINDSTR pode falhar ao encontrar um arquivo se o nome contiver caracteres ASCII estendidos e o nome do arquivo for especificado na linha de comando. Se um arquivo a ser pesquisado contiver ASCII estendido no nome, a /F:FILEopção deverá ser usada.

Aqui está uma lista completa das transformações de caracteres ASCII estendidas que o FINDSTR executa nas seqüências de caracteres da linha de comando. Cada caractere é representado como o valor do código de bytes decimais. O primeiro código representa o caractere conforme fornecido na linha de comando e o segundo código representa o caractere no qual ele é transformado. Nota - esta lista foi compilada em uma máquina nos EUA. Não sei qual o impacto que outros idiomas podem ter nessa lista.

158 treated as 080     199 treated as 221     226 treated as 071
169 treated as 170     200 treated as 043     227 treated as 112
176 treated as 221     201 treated as 043     228 treated as 083
177 treated as 221     202 treated as 045     229 treated as 115
178 treated as 221     203 treated as 045     231 treated as 116
179 treated as 221     204 treated as 221     232 treated as 070
180 treated as 221     205 treated as 045     233 treated as 084
181 treated as 221     206 treated as 043     234 treated as 079
182 treated as 221     207 treated as 045     235 treated as 100
183 treated as 043     208 treated as 045     236 treated as 056
184 treated as 043     209 treated as 045     237 treated as 102
185 treated as 221     210 treated as 045     238 treated as 101
186 treated as 221     211 treated as 043     239 treated as 110
187 treated as 043     212 treated as 043     240 treated as 061
188 treated as 043     213 treated as 043     242 treated as 061
189 treated as 043     214 treated as 043     243 treated as 061
190 treated as 043     215 treated as 043     244 treated as 040
191 treated as 043     216 treated as 043     245 treated as 041
192 treated as 043     217 treated as 043     247 treated as 126
193 treated as 045     218 treated as 043     249 treated as 250
194 treated as 045     219 treated as 221     251 treated as 118
195 treated as 043     220 treated as 095     252 treated as 110
196 treated as 045     222 treated as 221     254 treated as 221
197 treated as 043     223 treated as 095
198 treated as 221     224 treated as 097

Qualquer caractere> 0 que não esteja na lista acima é tratado como ele mesmo, incluindo <CR>e < LF>. A maneira mais fácil de incluir caracteres ímpares como <CR>e <LF>é colocá-los em uma variável de ambiente e usar a expansão atrasada no argumento da linha de comando.

Limites de caracteres para cadeias encontradas em arquivos especificados pelas opções / G: FILE e / F: FILE
O caractere nul (0x00) pode aparecer no arquivo, mas funciona como o terminador de cadeia C. Qualquer caractere após um caracter nulo é tratado como uma sequência diferente, como se estivesse em outra linha.

Os caracteres <CR>e <LF>são tratados como terminadores de linha que terminam uma sequência e não são incluídos na sequência.

Todos os outros caracteres de byte único são incluídos perfeitamente em uma string.

Pesquisando arquivos Unicode O
FINDSTR não pode pesquisar corretamente a maioria dos Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) porque não é possível procurar bytes nulos e o Unicode normalmente contém muitos bytes nulos.

No entanto, o comando TYPE converte UTF-16LE com BOM em um conjunto de caracteres de byte único; portanto, um comando como o seguinte funcionará com UTF-16LE com BOM.

type unicode.txt|findstr "search"

Observe que os pontos de código Unicode que não são suportados pela sua página de código ativa serão convertidos em ?caracteres.

É possível pesquisar em UTF-8 desde que sua string de pesquisa contenha apenas ASCII. No entanto, a saída do console de qualquer caractere UTF-8 de vários bytes não estará correta. Mas se você redirecionar a saída para um arquivo, o resultado será codificado corretamente em UTF-8. Observe que, se o arquivo UTF-8 contiver uma BOM, ela será considerada como parte da primeira linha, o que poderia desencadear uma pesquisa que corresponda ao início de uma linha.

É possível pesquisar caracteres UTF-8 de bytes múltiplos, se você colocar a sequência de caracteres de pesquisa em um arquivo de pesquisa codificado em UTF-8 (sem BOM) e usar a opção / G.

Fim da linha
FINDSTR quebra as linhas imediatamente após cada <LF>. A presença ou ausência de <CR> não afeta as quebras de linha.

Pesquisando Quebra de Linha
Como esperado, o .metacaractere regex não corresponderá a <CR> ou <LF>. Mas é possível pesquisar em uma quebra de linha usando uma string de pesquisa de linha de comando. Os caracteres <CR> e <LF> devem ser correspondidos explicitamente. Se uma correspondência de várias linhas for encontrada, apenas a 1ª linha da correspondência será impressa. O FINDSTR então volta para a segunda linha da fonte e inicia a busca novamente - uma espécie de recurso do tipo "olhar à frente".

Suponha que TEXT.TXT tenha esse conteúdo (pode ser do estilo Unix ou Windows)

A
A
A
B
A
A

Então este script

@echo off
setlocal
::Define LF variable containing a linefeed (0x0A)
set LF=^


::Above 2 blank lines are critical - do not remove

::Define CR variable containing a carriage return (0x0D)
for /f %%a in ('copy /Z "%~dpf0" nul') do set "CR=%%a"

setlocal enableDelayedExpansion
::regex "!CR!*!LF!" will match both Unix and Windows style End-Of-Line
findstr /n /r /c:"A!CR!*!LF!A" TEST.TXT

dá esses resultados

1:A
2:A
5:A

A pesquisa nas quebras de linha usando a opção / G: FILE é imprecisa porque a única maneira de corresponder a <CR> ou <LF> é através de uma expressão de intervalo de classe de caracteres regex que imprensa os caracteres EOL.

  • [<TAB>-<0x0B>] corresponde a <LF>, mas também corresponde a <TAB> e <0x0B>

  • [<0x0C>-!] corresponde a <CR>, mas também a <0x0C> e!

    Nota - as representações acima são simbólicas do fluxo de bytes regex, pois não posso representar graficamente os caracteres.

A resposta continua na parte 2 abaixo ...


45
Excelente completude. Se ao menos todas as respostas na internet fossem assim.
9138 Mike Viens

1
encontramos um problema addpath.batdo Q141344 e do findstr, que pode estar relacionado ao problema de suspensão do Win7 mencionado acima. Eu criei uma sala de chat para tentar controlar isso para baixo, para qualquer pessoa interessada: chat.stackoverflow.com/rooms/13177/...
Matt Wilkie

2
EDIT - Exibição descrita de caracteres de controle como pontos no XP. Também documentado erros /Se /Dopções decorrentes de nomes curtos de arquivo 8.3.
dbenham

1
EDIT - 1) Os nomes de arquivos dentro do arquivo especificado por / F: FILE não devem ser citados. 2) A transformação de caracteres ASCII estendidos afeta as cadeias de pesquisa e os nomes de arquivos quando fornecidos na linha de comandos.
dbenham

1
EDIT - Adicionado bug onde última linha de entrada encanada é ignorado se ele consiste em um único caractere sem<LF>
dbenham

64

A resposta continuou da parte 1 acima - eu atingi o limite de resposta de 30.000 caracteres :-(

Suporte
para expressões regulares limitadas (regex) O suporte do FINDSTR para expressões regulares é extremamente limitado. Se não estiver na documentação da AJUDA, não há suporte.

Além disso, as expressões regex suportadas são implementadas de maneira completamente fora do padrão, de modo que os resultados podem ser diferentes do que seria esperado, vindo de algo como grep ou perl.

As âncoras de posição da linha Regex ^ e $
^ correspondem ao início do fluxo de entrada, bem como a qualquer posição imediatamente após um <LF>. Como o FINDSTR também quebra as linhas após <LF>, uma simples expressão regular de "^" sempre corresponderá a todas as linhas de um arquivo, mesmo um arquivo binário.

$corresponde a qualquer posição imediatamente anterior a um <CR>. Isso significa que uma sequência de pesquisa de expressão regular que $nunca corresponderá a nenhuma linha de um arquivo de texto no estilo Unix, nem corresponderá à última linha de um arquivo de texto do Windows se estiver faltando o marcador EOL de <CR> <LF>.

Nota - Conforme discutido anteriormente, a entrada canalizada e redirecionada para o FINDSTR pode ter <CR><LF>acrescentado um anexo que não está na fonte. Obviamente, isso pode afetar uma pesquisa de regex usada $.

Qualquer string de pesquisa com caracteres antes ^ou depois $sempre falha em encontrar uma correspondência.

Opções posicionais / B / E / X
As opções posicionais funcionam da mesma forma que ^e $, exceto que também funcionam para cadeias de pesquisa literais.

/ B funciona da mesma maneira que ^no início de uma sequência de pesquisa de expressão regular.

/ E funciona da mesma forma que $no final de uma sequência de pesquisa de expressão regular.

/ X funciona da mesma forma que ^no início e $no final de uma sequência de pesquisa de expressão regular.

O limite da palavra
\< regex deve ser o primeiro termo na regex. A regex não corresponderá a nada se outros caracteres a precedem. \<corresponde ao início da entrada, ao início de uma linha (a posição imediatamente após um <LF>) ou a posição imediatamente após qualquer caractere "não palavra". O próximo caractere não precisa ser um caractere "palavra".

\>deve ser o último termo na regex. O regex não corresponderá a nada se outros caracteres o seguirem. \>corresponde ao final da entrada, à posição imediatamente anterior a um <CR> ou à posição imediatamente anterior a qualquer caractere "não palavra". O caractere anterior não precisa ser um caractere "palavra".

Aqui está uma lista completa de caracteres "não-palavra", representados como o código de bytes decimais. Nota - esta lista foi compilada em uma máquina nos EUA. Não sei qual o impacto que outros idiomas podem ter nessa lista.

001   028   063   179   204   230
002   029   064   180   205   231
003   030   091   181   206   232
004   031   092   182   207   233
005   032   093   183   208   234
006   033   094   184   209   235
007   034   096   185   210   236
008   035   123   186   211   237
009   036   124   187   212   238
011   037   125   188   213   239
012   038   126   189   214   240
014   039   127   190   215   241
015   040   155   191   216   242
016   041   156   192   217   243
017   042   157   193   218   244
018   043   158   194   219   245
019   044   168   195   220   246
020   045   169   196   221   247
021   046   170   197   222   248
022   047   173   198   223   249
023   058   174   199   224   250
024   059   175   200   226   251
025   060   176   201   227   254
026   061   177   202   228   255
027   062   178   203   229

Intervalos de classes de caracteres regex [xy]
Os intervalos de classes de caracteres não funcionam conforme o esperado. Veja esta pergunta: Por que o findstr não lida com o caso corretamente (em algumas circunstâncias)? , junto com esta resposta: https://stackoverflow.com/a/8767815/1012053 .

O problema é que o FINDSTR não agrupa os caracteres pelo valor do código de bytes (geralmente considerado o código ASCII, mas o ASCII é definido apenas de 0x00 a 0x7F). A maioria das implementações de regex trataria [AZ] como todas as letras maiúsculas em inglês. Mas o FINDSTR usa uma sequência de agrupamento que corresponde aproximadamente à maneira como o SORT funciona. Portanto, [AZ] inclui o alfabeto completo em inglês, letras maiúsculas e minúsculas (exceto "a"), além de caracteres alfabéticos não ingleses com diacríticos.

Abaixo está uma lista completa de todos os caracteres suportados pelo FINDSTR, classificados na sequência de intercalação usada pelo FINDSTR para estabelecer intervalos de classes de caracteres regex. Os caracteres são representados como seu valor de código de bytes decimais. Acredito que a sequência de intercalação faz mais sentido se os caracteres forem visualizados usando a página de códigos 437. Nota - essa lista foi compilada em uma máquina nos EUA. Não sei qual o impacto que outros idiomas podem ter nessa lista.

001
002
003
004
005
006
007
008
014
015
016
017
018           
019
020
021
022
023
024
025
026
027
028
029
030
031
127
039
045
032
255
009
010
011
012
013
033
034
035
036
037
038
040
041
042
044
046
047
058
059
063
064
091
092
093
094
095
096
123
124
125
126
173
168
155
156
157
158
043
249
060
061
062
241
174
175
246
251
239
247
240
243
242
169
244
245
254
196
205
179
186
218
213
214
201
191
184
183
187
192
212
211
200
217
190
189
188
195
198
199
204
180
181
182
185
194
209
210
203
193
207
208
202
197
216
215
206
223
220
221
222
219
176
177
178
170
248
230
250
048
172
171
049
050
253
051
052
053
054
055
056
057
236
097
065
166
160
133
131
132
142
134
143
145
146
098
066
099
067
135
128
100
068
101
069
130
144
138
136
137
102
070
159
103
071
104
072
105
073
161
141
140
139
106
074
107
075
108
076
109
077
110
252
078
164
165
111
079
167
162
149
147
148
153
112
080
113
081
114
082
115
083
225
116
084
117
085
163
151
150
129
154
118
086
119
087
120
088
121
089
152
122
090
224
226
235
238
233
227
229
228
231
237
232
234

Limite de termos da classe de caracteres de expressão regular e BUG O
FINDSTR não é limitado apenas a um máximo de 15 termos de classe de caracteres em uma expressão regular, mas falha ao lidar adequadamente com uma tentativa de exceder o limite. O uso de 16 ou mais termos de classe de caracteres resulta em um pop-up interativo do Windows informando "O utilitário Find String (QGREP) encontrou um problema e precisa fechar. Desculpe-nos pela inconveniência." O texto da mensagem varia um pouco, dependendo da versão do Windows. Aqui está um exemplo de um FINDSTR que falhará:

echo 01234567890123456|findstr [0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9][0-9]

Esse bug foi relatado pelo usuário do DosTips Judago aqui . Foi confirmado no XP, Vista e Windows 7.

As pesquisas de
regex falham (e podem travar indefinidamente) se incluirem o código de byte 0xFF (decimal 255) Qualquer pesquisa de regex que inclua o código de byte 0xFF (decimal 255) falhará. Falha se o código de byte 0xFF for incluído diretamente ou implicitamente estiver incluído em um intervalo de classe de caracteres. Lembre-se de que os intervalos da classe de caracteres FINDSTR não agrupam caracteres com base no valor do código de bytes. O caractere <0xFF>aparece relativamente cedo na sequência de intercalação entre os caracteres <space>e <tab>. Portanto, qualquer intervalo de classe de personagem que inclua os dois <space>e <tab>falhe.

O comportamento exato muda um pouco, dependendo da versão do Windows. O Windows 7 trava indefinidamente se 0xFF estiver incluído. O XP não trava, mas sempre falha ao encontrar uma correspondência e, ocasionalmente, imprime a seguinte mensagem de erro - "O processo tentou gravar em um canal inexistente".

Não tenho mais acesso a uma máquina Vista, portanto não pude testar no Vista.

Erro de.[^anySet]
regex : e pode corresponder ao final do arquivo O .meta-caractere regex deve corresponder apenas a qualquer caractere que não seja <CR>ou <LF>. Existe um erro que permite corresponder ao final do arquivo se a última linha do arquivo não for finalizada por <CR>ou <LF>. No entanto, o .arquivo não corresponderá a um arquivo vazio.

Por exemplo, um arquivo chamado "test.txt" contendo uma única linha de x, sem terminar <CR>ou <LF>, corresponderá ao seguinte:

findstr /r x......... test.txt

Este bug foi confirmado no XP e Win7.

O mesmo parece ser verdadeiro para conjuntos de caracteres negativos. Algo como [^abc]irá corresponder ao fim do arquivo. Conjuntos de caracteres positivos [abc]parecem funcionar bem. Eu só testei isso no Win7.


1
O findstr também é um buggy que lida com arquivos grandes. Arquivos> 2 GB podem causar a interrupção do findstr. Isso nem sempre acontece. Ao confirmar o erro, procurei um arquivo de 2,3 GB que não travou. Ele trava mesmo se estiver pesquisando apenas um único arquivo. A solução alternativa é canalizar a saída de typepara findstr.
Disillusioned

Também vale a pena mencionar explicitamente que findstrsuporta várias /c:cadeias de pesquisa. Eu sei que suas respostas demonstram isso. Mas é algo que não está documentado; e fiquei bastante surpreso ao saber do recurso depois de usá- findstrlo por alguns anos.
Disillusioned

@ CraigYoung - Você está certo sobre as fontes de sequência de pesquisa. Eu editei minha resposta, obrigado.
precisa saber é o seguinte

1
Em uma investigação mais aprofundada, parece uma variação do LFproblema que você documentou. Percebi que meu arquivo de teste não terminou LFporque usei copyno modo de acréscimo para criá-lo. Eu coloquei uma sessão de linha de comando para demonstrar o problema em uma resposta ( stackoverflow.com/a/22943056/224704 ). Observe que a entrada não é redirecionada e, no entanto, a pesquisa trava. O mesmo comando de pesquisa exato não trava com arquivos menores que da mesma forma não terminam LF.
Desiludido

1
Nova descoberta (Win7): findstr /R /C:"^[0-9][0-9]* [0-3][0-9][0-9]-[0-9][0-9]:[0-5][0-9]:[0-5][0-9]\.[0-9][0-9]* [0-9]*\.[0-9]*"(15 classes de personagens) - ErrorLevel = -1073740791 (0xC0000409), a janela de diálogo de erro : Find String (QGREP) Utility has stopped working; após a remoção de uma classe ou dois caracteres Meta ( *\.), ele funciona ...
aschipfl

7

findstr às vezes trava inesperadamente ao pesquisar arquivos grandes.

Não confirmei as condições exatas ou os tamanhos dos limites. Eu suspeito que qualquer arquivo maior de 2 GB pode estar em risco.

Eu tive experiências mistas com isso, por isso é mais do que apenas o tamanho do arquivo. Parece que pode haver uma variação no FINDSTR travar no XP e no Windows 7 se a entrada redirecionada não terminar com LF , mas, como demonstrado, esse problema específico se manifesta quando a entrada não é redirecionada.

A seguinte sessão de linha de comando (Windows 7) demonstra como findstrtravar ao pesquisar um arquivo de 3 GB.

C:\Data\Temp\2014-04>echo 1234567890123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890> T100B.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,10) do @type T100B.txt >> T1KB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1KB.txt >> T1MB.txt

C:\Data\Temp\2014-04>for /L %i in (1,1,1000) do @type T1MB.txt >> T1GB.txt

C:\Data\Temp\2014-04>echo find this line>> T1GB.txt

C:\Data\Temp\2014-04>copy T1GB.txt + T1GB.txt + T1GB.txt T3GB.txt
T1GB.txt
T1GB.txt
T1GB.txt
        1 file(s) copied.

C:\Data\Temp\2014-04>dir
 Volume in drive C has no label.
 Volume Serial Number is D2B2-FFDF

 Directory of C:\Data\Temp\2014-04

2014/04/08  04:28 PM    <DIR>          .
2014/04/08  04:28 PM    <DIR>          ..
2014/04/08  04:22 PM               102 T100B.txt
2014/04/08  04:28 PM     1 020 000 016 T1GB.txt
2014/04/08  04:23 PM             1 020 T1KB.txt
2014/04/08  04:23 PM         1 020 000 T1MB.txt
2014/04/08  04:29 PM     3 060 000 049 T3GB.txt
               5 File(s)  4 081 021 187 bytes
               2 Dir(s)  51 881 050 112 bytes free
C:\Data\Temp\2014-04>rem Findstr on the 1GB file does not hang

C:\Data\Temp\2014-04>findstr "this" T1GB.txt
find this line

C:\Data\Temp\2014-04>rem On the 3GB file, findstr hangs and must be aborted... even though it clearly reaches end of file

C:\Data\Temp\2014-04>findstr "this" T3GB.txt
find this line
find this line
find this line
^C
C:\Data\Temp\2014-04>

Observe que eu verifiquei em um editor hexadecimal que todas as linhas são encerradas CRLF. A única anomalia é que o arquivo é finalizado 0x1Adevido ao modo como copyfunciona . Observe, no entanto, que essa anomalia não causa problemas em arquivos "pequenos" .

Com testes adicionais, confirmei o seguinte:

  • O uso copyda /bopção para arquivos binários impede a adição do 0x1Acaractere e findstrnão fica suspenso no arquivo de 3 GB.
  • A finalização do arquivo de 3 GB com um caractere diferente também faz com que findstra paralise.
  • O 0x1Apersonagem não causa problemas em um arquivo "pequeno". (Da mesma forma para outros caracteres finais).
  • Adicionar CRLFdepois 0x1Aresolve o problema. ( LFpor si só provavelmente seria suficiente.)
  • Usando typepara canalizar o arquivo em findstrobras sem travar. (Isso pode ser devido a um efeito colateral de um typeou |que insere um fim de linha adicional.)
  • Usar entrada redirecionada <também causa findstrtravamento. Mas isso é esperado; como explicado no post do dbenham : "a entrada redirecionada deve terminar em LF" .

1
+1, posso confirmar o problema na minha máquina Win7. Um arquivo com tamanho exatamente de 2 GiB travou quando o último caractere não estava <LF>. Um arquivo dois bytes menor não foi interrompido. Muito nojento!
precisa saber é o seguinte

6

Quando vários comandos estão entre parênteses e há arquivos redirecionados para todo o bloco:

< input.txt (
   command1
   command2
   . . .
) > output.txt

... os arquivos permanecerão abertos enquanto os comandos do bloco estiverem ativos, para que os comandos possam mover o ponteiro dos arquivos redirecionados. Os comandos MORE e FIND movem o ponteiro do arquivo Stdin para o início do arquivo antes de processá-lo, para que o mesmo arquivo possa ser processado várias vezes dentro do bloco. Por exemplo, este código:

more < input.txt >  output.txt
more < input.txt >> output.txt

... produz o mesmo resultado que este:

< input.txt (
   more
   more
) > output.txt

Este código:

find    "search string" < input.txt > matchedLines.txt
find /V "search string" < input.txt > unmatchedLines.txt

... produz o mesmo resultado que este:

< input.txt (
   find    "search string" > matchedLines.txt
   find /V "search string" > unmatchedLines.txt
)

FINDSTR é diferente; ele não move o ponteiro do arquivo Stdin de sua posição atual. Por exemplo, esse código insere uma nova linha após uma linha de pesquisa:

call :ProcessFile < input.txt
goto :EOF

:ProcessFile
   rem Read the next line from Stdin and copy it
   set /P line=
   echo %line%
   rem Test if it is the search line
   if "%line%" neq "search line" goto ProcessFile
rem Insert the new line at this point
echo New line
rem And copy the rest of lines
findstr "^"
exit /B

Podemos fazer bom uso desse recurso com a ajuda de um programa auxiliar que nos permite mover o ponteiro do arquivo redirecionado, como mostra este exemplo .

Este comportamento foi primeiramente relatada por jeb a este post .


EDIT 2018-08-18 : Novo bug do FINDSTR relatado

O comando FINDSTR possui um erro estranho que ocorre quando esse comando é usado para mostrar caracteres em cores E a saída desse comando é redirecionada para o dispositivo CON. Para obter detalhes sobre como usar o comando FINDSTR para mostrar texto em cores, consulte este tópico .

Quando a saída dessa forma de comando FINDSTR é redirecionada para CON, algo estranho acontece depois que o texto é exibido na cor desejada: todo o texto após ele é exibido como caracteres "invisíveis", embora uma descrição mais precisa seja o texto. saída como texto em preto sobre fundo preto. O texto original será exibido se você usar o comando COLOR para redefinir as cores de primeiro e segundo plano da tela inteira. No entanto, quando o texto é "invisível", podemos executar um comando SET / P, para que todos os caracteres digitados não apareçam na tela. Esse comportamento pode ser usado para inserir senhas.

@echo off
setlocal

set /P "=_" < NUL > "Enter password"
findstr /A:1E /V "^$" "Enter password" NUL > CON
del "Enter password"
set /P "password="
cls
color 07
echo The password read is: "%password%"

2

Eu gostaria de relatar um erro referente à seção Fonte de dados para pesquisar na primeira resposta ao usar en dash (-) ou em dash (-) dentro do nome do arquivo.

Mais especificamente, se você estiver prestes a usar a primeira opção - nomes de arquivos especificados como argumentos , o arquivo não será encontrado. Assim que você usar a opção 2 - stdin via redirecionamento ou 3 - fluxo de dados de um canal, o findstr encontrará o arquivo.

Por exemplo, este script em lote simples:

echo off
chcp 1250 > nul
set INTEXTFILE1=filename with – dash.txt
set INTEXTFILE2=filename with — dash.txt

rem 3 way of findstr use with en dashed filename
echo.
echo Filename with en dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE1%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE1%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE1%" | findstr .
echo.
echo.
rem The same set of operations with em dashed filename
echo Filename with em dash:
echo.
echo 1. As argument
findstr . "%INTEXTFILE2%"
echo.
echo 2. As stdin via redirection
findstr . < "%INTEXTFILE2%"
echo.
echo 3. As datastream from a pipe
type "%INTEXTFILE2%" | findstr .
echo.

pause

irá imprimir:

Nome do arquivo com traço:

  1. Como argumento
    FINDSTR: Não é possível abrir o nome do arquivo com - dash.txt

  2. Como stdin via redirecionamento,
    eu sou o arquivo com um traço.

  3. Como fluxo de dados de um pipe,
    eu sou o arquivo com um traço.

Nome do arquivo com em dash:

  1. Como argumento
    FINDSTR: Não é possível abrir o nome do arquivo com - dash.txt

  2. Como stdin via redirecionamento,
    eu sou o arquivo com um traço em.

  3. Como fluxo de dados de um pipe,
    eu sou o arquivo com um traço em.

Espero que ajude.

M.


1
Olá, matro, embora seus comentários possam estar corretos, não tenho certeza de que eles não abordem a questão real.
Wai Ha Lee

Eu acredito que este é um problema unicode, que o FINDSTR não suporta. O redirecionamento do CMD.EXE pode abrir corretamente um nome de arquivo com unicode, assim como o comando TYPE. Mas em algum momento, o FINDSTR converte o traço e o traço em traço normal e, é claro, o sistema operacional não consegue encontrar esse nome. Se você criar outro arquivo substituindo um traço pelo traço e / ou traço, o FINDSTR pesquisará o arquivo do traço se for fornecido um nome que contenha traço ou traço.
dbenham

Eu classificaria esse problema como uma limitação e não um bug.
dbenham

Na verdade, esse não é um problema unicode, mas sim um ASCII estendido. Eu já documentei esse problema na minha resposta original, sob o título Limites de caracteres para os parâmetros da linha de comando - transformação ASCII estendida . O FINDSTR transforma vários códigos ASCII estendidos em ASCII verdadeiro "relacionado", incluindo o en-dash e em-dash.
precisa

1

O findstrcomando define o ErrorLevel(ou código de saída) para um dos seguintes valores, dado que não há opções inválidas ou incompatíveis e nenhuma cadeia de pesquisa excede o limite de comprimento aplicável:

  • 0 quando pelo menos uma única correspondência for encontrada em uma linha em todos os arquivos especificados;
  • 1 de outra forma;

Uma linha é considerada como contendo uma correspondência quando:

  • nenhuma /Vopção é fornecida e a expressão de pesquisa ocorre pelo menos uma vez;
  • a /Vopção é dada e a expressão de pesquisa não ocorre;

Isso significa que a /Vopção também altera a retornada ErrorLevel, mas não apenas a reverte!

Por exemplo, quando você tem um arquivo test.txt com duas linhas, uma das quais contém a sequência, textmas a outra não, ambas findstr "text" "test.txt"e findstr /V "text" "test.txt"retorna um ErrorLevelde 0.

Basicamente, você pode dizer: se findstrretorna pelo menos uma linha, ErrorLevelestá definido como 0, caso contrário, para 1.

Observe que a /Mopção não afeta o ErrorLevelvalor, apenas altera a saída.

(Apenas por uma questão de integridade: o findcomando se comporta exatamente da mesma maneira com relação à /Vopção e ErrorLevel; a /Copção não afeta ErrorLevel.)


1

O FINDSTR possui um erro de cor que descrevi e resolvi em /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Para resumir esse segmento, o erro é que, se a entrada é canalizada para FINDSTR dentro de um bloco de código entre parênteses, os códigos de cores de escape ANSI embutidos param de funcionar nos comandos executados posteriormente. Um exemplo de códigos de cores embutidos é:echo %magenta%Alert: Something bad happened%yellow% (onde magenta e amarelo são vars definidos anteriormente no arquivo .bat como os códigos de cores de escape ANSI correspondentes).

Minha solução inicial foi chamar uma sub-rotina do-nothing após o FINDSTR. De alguma forma, a chamada ou o retorno "redefine" o que precisar ser redefinido.

Mais tarde, descobri outra solução que presumivelmente é mais eficiente: coloque a frase FINDSTR entre parênteses, como no exemplo a seguir: echo success | ( FINDSTR /R success ) Colocar a frase FINDSTR em um bloco de código aninhado parece isolar o bug do código de cores do FINDSTR para que não afete o que está fora do aninhado quadra. Talvez essa técnica resolva outros efeitos colaterais indesejados do FINDSTR também .


Ótima descoberta. Mas suas regras podem ser simplificadas (pelo menos na minha máquina Windows 10 corporativa). O FINDSTR impede que todas as seqüências de escape do console funcionem para comandos subseqüentes no mesmo bloco de comandos. Não importa se o FINDSTR lê um canal, entrada redirecionada ou arquivo. A falha na sequência de escape não se restringe aos códigos de cores. Um bloco de comando é qualquer conjunto de comandos entre parênteses e / ou comandos concatenados por &, && ou ||
dbenham 9/04

@dbenham: Boa generalização do problema. Você sabe se minha solução - aninhando a frase FINDSTR entre parênteses - funciona também no caso geral? E você sabe se minha solução tem efeitos colaterais indesejáveis?
Dolores Stevens

Eu não fiz nenhum teste exaustivo, mas sim, os parênteses aninhados parecem ser uma solução geral e não consigo pensar em possíveis efeitos colaterais indesejáveis.
dbenham 9/04

-1

/ D dica para vários diretórios: coloque sua lista de diretórios antes da string de pesquisa. Tudo isso funciona:

findstr /D:dir1;dir2 "searchString" *.*
findstr /D:"dir1;dir2" "searchString" *.*
findstr /D:"\path\dir1\;\path\dir2\" "searchString" *.*

Como esperado, o caminho é relativo ao local se você não iniciar os diretórios com \. Rodear o caminho com "é opcional se não houver espaços nos nomes dos diretórios. O final \é opcional. A saída do local incluirá qualquer caminho que você indicar. Ele funcionará com ou sem cercar a lista de diretórios com ".


Não vejo nada indocumentado aqui. A opção / D é descrita na ajuda interna. Esta não é uma pergunta para dicas gerais sobre como usar o FINDSTR. Destina-se estritamente a listar recursos, limitações e / ou bugs não documentados.
dbenham

1
@dbenham verdade, não é realmente indocumentado, mas descobri que precisava trabalhar com o findstr para obter os resultados desejados e estou compartilhando o que encontrei DID funcionou para que as pessoas não perdessem tempo experimentando comandos que não funcionam. hth (estou triste você não gosta de minha entrada - ele só foi destinado a ser construtiva)
gordon

IMHO, a opção / D está claramente descrita na ajuda incorporada: /D:dirlist Search a semicolon-delimited list of directoriese é colocada antes da sequência de pesquisa, por isso não entendo exatamente o que "você encontrou" sobre a opção / D (e quais são os "comandos" não funciona ") ...
Aacini

@Aacini em muitos idiomas, a ordem dos atributos não importa. Eu entendo a documentação das findstrlistas / D primeiro. Sim, não tenho argumentos com o recurso sendo documentado, apenas não está documentado sobre o problema que importa a ordem dos atributos. Como faço muito pouco trabalho de linha de comando, portanto, quando eu estava executando um comando, sem perceber que a ordem fazia diferença, estava apenas adicionando os atributos conforme cheguei a eles (e em ordem alfabética, C precede D). Fiquei muito frustrado e compartilhei minha experiência "encontrada" para qualquer pessoa que não trabalhe muito com a linha de comando.
gordon

1
A ordem dos atributos opcionais geralmente não importa. A findstrdocumentação especifica que a stringsparte NÃO é opcional e que você deve colocá-la após os atributos opcionais e antes da lista de nome de arquivo opcional . Se "o que você encontrou" é que o uso de um comando sem seguir seu formato de uso causa um erro, esse ponto está bem documentado. Consulte Sintaxe de comando : "A sintaxe aparece na ordem em que você deve digitar um comando e todos os parâmetros que o seguem"
Aacini
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.