Quelles sont les fonctionnalités et limitations non documentées de la commande Windows FINDSTR?

191

La commande Windows FINDSTR est horriblement documentée. Une aide de ligne de commande très basique est disponible via FINDSTR /?ou HELP FINDSTR, mais elle est malheureusement insuffisante. Il existe un tout petit peu plus de documentation en ligne à l' adresse https://docs.microsoft.com/en-us/windows-server/administration/windows-commands/findstr .

Il existe de nombreuses fonctionnalités et limitations de FINDSTR qui ne sont même pas mentionnées dans la documentation. Ils ne pourraient pas non plus être anticipés sans connaissance préalable et / ou expérimentation minutieuse.

La question est donc: quelles sont les fonctionnalités et limitations non documentées de FINDSTR?

Le but de cette question est de fournir un référentiel unique des nombreuses fonctionnalités non documentées afin que:

A) Les développeurs peuvent profiter pleinement des fonctionnalités disponibles.

B) Les développeurs ne perdent pas leur temps à se demander pourquoi quelque chose ne fonctionne pas alors que cela semble normal.

Veuillez vous assurer que vous connaissez la documentation existante avant de répondre. Si les informations sont couvertes par l'AIDE, elles n'appartiennent pas ici.

Ce n'est pas non plus un endroit pour montrer des utilisations intéressantes de FINDSTR. Si une personne logique pouvait anticiper le comportement d'une utilisation particulière de FINDSTR sur la base de la documentation, alors cela n'a pas sa place ici.

Dans le même ordre d'idées, si une personne logique pouvait anticiper le comportement d'un usage particulier sur la base d'informations contenues dans des réponses existantes, alors encore une fois, cela n'a pas sa place ici.

Dbenham
la source
15
Ou, alternativement, vous pouvez abandonner complètement l'utilitaire MS non documenté merdique et installer / utiliser grepqui est très bien compris et documenté :-) Voir stackoverflow.com/questions/2635740/… par exemple.
paxdiablo
18
Bien sûr, si vous êtes en mesure d'utiliser autre chose que FINDSTR, alors cela est fortement conseillé. Mais certaines personnes se trouvent dans des environnements où les utilitaires tiers sont interdits.
dbenham
5
Aucune offense prise. J'ai sérieusement envisagé d'ajouter mon propre avertissement FINDSTR qui était similaire à votre commentaire! :)
dbenham
41
Je suis choqué et déçu que quelqu'un trouve cette question «non constructive» et vote pour la fermer. La question a fait l'objet de beaucoup de réflexion pour éviter «les opinions, les débats, les arguments, les sondages ou les discussions prolongées». La question est postée depuis 3,5 mois et aucun des négatifs cités ne s'est produit. La réponse jumelée est remplie de faits et a nécessité de nombreuses heures de recherche et d'expérimentation minutieuses.
dbenham
6
Certains lecteurs peuvent être intéressés par le contexte historique de la commande findstr
Harry Johnston

Réponses:

283

Préface La
plupart des informations contenues dans cette réponse ont été recueillies sur la base d'expériences exécutées sur une machine Vista. Sauf indication contraire explicite, je n'ai pas confirmé si les informations s'appliquent à d'autres versions de Windows.

Sortie FINDSTR
La documentation ne se soucie jamais d'expliquer la sortie de FINDSTR. Cela fait allusion au fait que les lignes correspondantes sont imprimées, mais rien de plus.

Le format de la sortie de ligne correspondante est le suivant:

nom de fichier: lineNumber: lineOffset: texte

fileName: = Le nom du fichier contenant la ligne correspondante. Le nom du fichier n'est pas imprimé si la demande concernait explicitement un seul fichier, ou si la recherche d'une entrée canalisée ou d'une entrée redirigée. Une fois imprimé, le fileName inclura toujours toutes les informations de chemin fournies. Des informations de chemin supplémentaires seront ajoutées si l'/Soption est utilisée. Le chemin imprimé est toujours relatif au chemin fourni, ou relatif au répertoire courant si aucun n'est fourni.

Remarque - Le préfixe de nom de fichier peut être évité lors de la recherche de plusieurs fichiers en utilisant les caractères génériques non standard (et mal documentés) < et >. Les règles exactes du fonctionnement de ces caractères génériques peuvent être trouvées ici . Enfin, vous pouvez regarder cet exemple de fonctionnement des caractères génériques non standard avec FINDSTR .

lineNumber: = Le numéro de ligne de la ligne correspondante représentée sous forme de valeur décimale avec 1 représentant la 1ère ligne de l'entrée. Imprimé uniquement si l'/Noption est spécifiée.

lineOffset: = Le décalage d'octet décimal du début de la ligne correspondante, 0 représentant le 1er caractère de la 1ère ligne. Imprimé uniquement si l'/Ooption est spécifiée. Ce n'est pas le décalage de la correspondance dans la ligne. C'est le nombre d'octets entre le début du fichier et le début de la ligne.

text = La représentation binaire de la ligne correspondante, y compris tout <CR> et / ou <LF>. Rien n'est laissé en dehors de la sortie binaire, de sorte que cet exemple qui correspond à toutes les lignes produira une copie binaire exacte du fichier d'origine.

FINDSTR "^" FILE >FILE_COPY

L'option / A définit la couleur du fileName :, lineNumber: et lineOffset: sortie uniquement. Le texte de la ligne correspondante est toujours affiché avec la couleur actuelle de la console. L'option / A n'a d'effet que lorsque la sortie est affichée directement sur la console. L'option / A n'a aucun effet si la sortie est redirigée vers un fichier ou redirigée. Voir la modification du 18/08/2018 dans la réponse d' Aacini pour une description du comportement bogué lorsque la sortie est redirigée vers CON.

La plupart des caractères de contrôle et de nombreux caractères ASCII étendus s'affichent sous forme de points sur XP
FINDSTR sur XP affiche la plupart des caractères de contrôle non imprimables des lignes correspondantes sous forme de points (points) à l'écran. Les caractères de contrôle suivants sont des exceptions; ils s'affichent comme eux-mêmes: 0x09 Tab, 0x0A LineFeed, 0x0B Vertical Tab, 0x0C Form Feed, 0x0D Carriage Return.

XP FINDSTR convertit également un certain nombre de caractères ASCII étendus en points. Les caractères ASCII étendus qui s'affichent sous forme de points sur XP sont les mêmes que ceux qui sont transformés lorsqu'ils sont fournis sur la ligne de commande. Voir la section «Limites de caractères pour les paramètres de ligne de commande - Transformation ASCII étendue» , plus loin dans cet article

Les caractères de contrôle et l'ASCII étendu ne sont pas convertis en points sur XP si la sortie est redirigée vers un fichier ou dans une clause FOR IN ().

Vista et Windows 7 affichent toujours tous les caractères comme eux-mêmes, jamais sous forme de points.

Codes de retour (ERRORLEVEL)

  • 0 (succès)
    • Une correspondance a été trouvée dans au moins une ligne d'au moins un fichier.
  • 1 (échec)
    • Aucune correspondance n'a été trouvée dans aucune ligne d'un fichier.
    • Couleur non valide spécifiée par l' /A:xxoption
  • 2 (erreur)
    • Options incompatibles /Let les /Rdeux spécifiées
    • Argument manquant après /A:, /F:, /C:, /D:ou/G:
    • Fichier spécifié par /F:fileou /G:fileintrouvable
  • 255 (erreur)

Source des données à rechercher (mise à jour en fonction de tests avec Windows 7)
Findstr peut rechercher des données à partir d'une seule des sources suivantes:

  • noms de fichiers spécifiés comme arguments et / ou en utilisant l' /F:fileoption.

  • stdin via la redirection findstr "searchString" <file

  • flux de données depuis un tube type file | findstr "searchString"

Les arguments / options ont priorité sur la redirection, qui a la priorité sur les données acheminées.

Arguments de nom de fichier et /F:filepeuvent être combinés. Plusieurs arguments de nom de fichier peuvent être utilisés. Si plusieurs /F:fileoptions sont spécifiées, seule la dernière est utilisée. Les caractères génériques sont autorisés dans les arguments de nom de fichier, mais pas dans le fichier pointé par /F:file.

Source des chaînes de recherche (mise à jour basée sur des tests avec Windows 7)
Les options /G:fileet /C:stringpeuvent être combinées. Plusieurs /C:stringoptions peuvent être spécifiées. Si plusieurs /G:fileoptions sont spécifiées, seule la dernière est utilisée. Si l'un /G:fileou l' autre /C:stringest utilisé, tous les arguments sans option sont supposés être des fichiers à rechercher. Si ni /G:fileni /C:stringn'est utilisé, alors le premier argument sans option est traité comme une liste délimitée par des espaces de termes de recherche.

Les noms de fichiers ne doivent pas être cités dans le fichier lors de l'utilisation de l' /F:FILEoption.
Les noms de fichiers peuvent contenir des espaces et d'autres caractères spéciaux. La plupart des commandes exigent que ces noms de fichiers soient cités. Mais l' /F:files.txtoption FINDSTR exige que les noms de fichiers dans files.txt ne soient PAS entre guillemets. Le fichier ne sera pas trouvé si le nom est cité.

BOGUE - Les noms de fichiers 8.3 courts peuvent casser les options /Det/S
Comme avec toutes les commandes Windows, FINDSTR tentera de faire correspondre à la fois le nom long et le nom court 8.3 lors de la recherche de fichiers à rechercher. Supposons que le dossier actuel contient les fichiers non vides suivants:

b1.txt
b.txt2
c.txt

La commande suivante trouvera avec succès les 3 fichiers:

findstr /m "^" *.txt

b.txt2correspond car le nom court correspondant B9F64~1.TXTcorrespond. Ceci est cohérent avec le comportement de toutes les autres commandes Windows.

Mais un bogue avec les options /Det /Sfait que les commandes suivantes ne trouvent queb1.txt

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

Le bogue empêche b.txt2d'être trouvé, ainsi que tous les noms de fichiers qui trient après b.txt2dans le même répertoire. Des fichiers supplémentaires qui sont triés avant, comme a.txt, sont trouvés. Des fichiers supplémentaires qui sont triés plus tard, comme d.txt, sont manqués une fois le bogue déclenché.

Chaque répertoire recherché est traité indépendamment. Par exemple, l' /Soption commencerait avec succès la recherche dans un dossier enfant après avoir échoué à trouver des fichiers dans le parent, mais une fois que le bogue ferait manquer un nom de fichier court à l'enfant, tous les fichiers suivants dans ce dossier enfant seraient également manqués .

Les commandes fonctionnent sans bogue si les mêmes noms de fichiers sont créés sur une machine sur laquelle la génération de noms NTFS 8.3 est désactivée. Bien sûr b.txt2, ne serait pas trouvé, mais c.txtserait trouvé correctement.

Tous les noms courts ne déclenchent pas le bogue. Toutes les instances de comportement bogué que j'ai vues impliquent une extension de plus de 3 caractères avec un nom court 8.3 qui commence de la même manière qu'un nom normal qui ne nécessite pas un nom 8.3.

Le bogue a été confirmé sur XP, Vista et Windows 7.

Caractères non imprimables et /Poption
L' /Poption oblige FINDSTR à ignorer tout fichier contenant l'un des codes d'octets décimaux suivants:
0-7, 14-25, 27-31.

En d'autres termes, l' /Poption ignorera uniquement les fichiers contenant des caractères de contrôle non imprimables. Les caractères de contrôle sont des codes inférieurs ou égaux à 31 (0x1F). FINDSTR traite les caractères de contrôle suivants comme imprimables:

 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)

Tous les autres caractères de contrôle sont traités comme non imprimables, dont la présence fait que l' /Poption ignore le fichier.

L'entrée canalisée et redirigée peut avoir été <CR><LF>ajoutée
Si l'entrée est canalisée et que le dernier caractère du flux ne l'est pas <LF>, alors FINDSTR s'ajoutera automatiquement <CR><LF>à l'entrée. Cela a été confirmé sur XP, Vista et Windows 7. (J'avais l'habitude de penser que le canal Windows était responsable de la modification de l'entrée, mais j'ai depuis découvert que FINDSTR est en train de faire la modification.)

Il en va de même pour les entrées redirigées sur Vista. Si le dernier caractère d'un fichier utilisé comme entrée redirigée ne l'est pas <LF>, FINDSTR s'ajoutera automatiquement <CR><LF>à l'entrée. Cependant, XP et Windows 7 ne modifient pas l'entrée redirigée.

FINDSTR se bloque sur XP et Windows 7 si l'entrée redirigée ne se termine pas par<LF>
Ceci est une "fonctionnalité" désagréable sur XP et Windows 7. Si le dernier caractère d'un fichier utilisé comme entrée redirigée ne se termine pas par <LF>, alors FINDSTR se bloquera indéfiniment une fois qu'il atteint la fin du fichier redirigé.

La dernière ligne de données Piped peut être ignorée si elle se compose d'un seul caractère.
Si l'entrée est redirigée et que la dernière ligne se compose d'un seul caractère qui n'est pas suivi de <LF>, FINDSTR ignore complètement la dernière ligne.

Exemple - La première commande avec un seul caractère et non <LF>ne correspond pas, mais la deuxième commande avec 2 caractères fonctionne bien, tout comme la troisième commande qui a un caractère avec une nouvelle ligne de fin.

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

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

> echo x| findstr "^"
x

Rapporté par l'utilisateur de DosTips Sponge Belly au nouveau bug de findstr . Confirmé sur XP, Windows 7 et Windows 8. Je n'ai pas encore entendu parler de Vista. (Je n'ai plus Vista à tester).

Syntaxe des
options Les lettres des options ne sont pas sensibles à la casse /iet /Isont donc équivalentes.

Les options peuvent être préfixées avec l'un /ou l' autre ou Les - options peuvent être concaténées après un seul /ou -. Cependant, la liste d'options concaténée peut contenir au plus une option à plusieurs caractères telle que OFF ou F :, et l'option à plusieurs caractères doit être la dernière option de la liste.

Ce qui suit sont toutes des manières équivalentes d'exprimer une recherche regex insensible à la casse pour toute ligne contenant à la fois «bonjour» et «au revoir» dans n'importe quel ordre

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

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

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

Des options peuvent également être citées. Alors /i, -i, "/i"et "-i"sont tous équivalents. De même, /c:string, "/c":string, "/c:"stringet "/c:string"sont tous équivalents.

Si une chaîne de recherche commence par un littéral /ou -, l' option /Cou /Gdoit être utilisée. Merci à Stephan d' avoir signalé cela dans un commentaire (supprimé depuis).

Limites de longueur de chaîne de recherche
Sous Vista, la longueur maximale autorisée pour une seule chaîne de recherche est de 511 octets. Si une chaîne de recherche dépasse 511, le résultat est une FINDSTR: Search string too long.erreur avec ERRORLEVEL 2.

Lors d'une recherche d'expression régulière, la longueur maximale de la chaîne de recherche est de 254. Une expression régulière d'une longueur comprise entre 255 et 511 entraînera une FINDSTR: Out of memoryerreur avec ERRORLEVEL 2. Une longueur d'expression régulière> 511 entraîne l' FINDSTR: Search string too long.erreur.

Sous Windows XP, la longueur de la chaîne de recherche est apparemment plus courte. Erreur Findstr: "Chaîne de recherche trop longue": Comment extraire et faire correspondre la sous-chaîne dans la boucle "for"? La limite XP est de 127 octets pour les recherches littérales et regex.

Limites de longueur de ligne Les
fichiers spécifiés comme argument de ligne de commande ou via l'option / F: FILE n'ont pas de limite de longueur de ligne connue. Les recherches ont été exécutées avec succès sur un fichier de 128 Mo qui ne contenait pas un seul <LF>.

Les données canalisées et l'entrée redirigée sont limitées à 8191 octets par ligne. Cette limite est une "fonctionnalité" de FINDSTR. Il n'est pas inhérent aux tuyaux ou à la redirection. FINDSTR utilisant une entrée stdin redirigée ou une entrée redirigée ne correspondra jamais à une ligne supérieure à 8 ko. Les lignes> = 8k génèrent un message d'erreur à stderr, mais ERRORLEVEL est toujours égal à 0 si la chaîne de recherche se trouve dans au moins une ligne d'au moins un fichier.

Type de recherche par défaut: Literal vs Regular Expression
/C:"string" - La valeur par défaut est / L literal. Combiner explicitement l'option / L avec / C: "string" fonctionne certes mais est redondant.

"string argument"- La valeur par défaut dépend du contenu de la toute première chaîne de recherche. (N'oubliez pas que <space> est utilisé pour délimiter les chaînes de recherche.) Si la première chaîne de recherche est une expression régulière valide qui contient au moins un méta-caractère non échappé, toutes les chaînes de recherche sont traitées comme des expressions régulières. Sinon, toutes les chaînes de recherche sont traitées comme des littéraux. Par exemple, "51.4 200"sera traitée comme deux expressions régulières car la première chaîne contient un point non échappé, alors "200 51.4"qu'elle sera traitée comme deux littéraux car la première chaîne ne contient aucun méta-caractère.

/G:file- La valeur par défaut dépend du contenu de la première ligne non vide du fichier. Si la première chaîne de recherche est une expression régulière valide contenant au moins un méta-caractère non échappé, toutes les chaînes de recherche sont traitées comme des expressions régulières. Sinon, toutes les chaînes de recherche sont traitées comme des littéraux.

Recommandation - Spécifiez toujours explicitement /Ll'option littérale ou l' /Roption d'expression régulière lorsque vous utilisez "string argument"ou /G:file.

BOGUE - La spécification de plusieurs chaînes de recherche littérales peut donner des résultats peu fiables

L'exemple simple FINDSTR suivant ne parvient pas à trouver une correspondance, même s'il le devrait.

echo ffffaaa|findstr /l "ffffaaa faffaffddd"

Ce bogue a été confirmé sur Windows Server 2003, Windows XP, Vista et Windows 7.

D'après des expériences, FINDSTR peut échouer si toutes les conditions suivantes sont remplies:

  • La recherche utilise plusieurs chaînes de recherche littérales
  • Les chaînes de recherche sont de longueurs différentes
  • Une chaîne de recherche courte présente un certain chevauchement avec une chaîne de recherche plus longue
  • La recherche est sensible à la casse (aucune /Ioption)

Dans chaque échec que j'ai vu, c'est toujours l'une des chaînes de recherche les plus courtes qui échoue.

Pour plus d'informations, consultez Pourquoi cet exemple FINDSTR avec plusieurs chaînes de recherche littérales ne trouve-t-il pas une correspondance?

Citations et backslahses dans les arguments de ligne de commande
Remarque - Les commentaires de l'utilisateur MC ND reflètent les règles horriblement compliquées de cette section. Il y a 3 phases d'analyse distinctes impliquées:

  • Le premier cmd.exe peut exiger que quelques guillemets soient échappés sous la forme ^ "(vraiment rien à voir avec FINDSTR)
  • Ensuite, FINDSTR utilise l' analyseur d'arguments MS C / C ++ antérieur à 2008 , qui a des règles spéciales pour "et \
  • Une fois l'analyseur d'arguments terminé, FINDSTR traite en outre \ suivi d'un caractère alphanumérique comme littéral, mais \ suivi d'un caractère non alphanumérique comme caractère d'échappement

Le reste de cette section en surbrillance n'est pas correct à 100%. Il peut servir de guide dans de nombreuses situations, mais les règles ci-dessus sont nécessaires pour une compréhension totale.

Échapper le devis dans les chaînes de recherche de ligne de commande Les
devis dans les chaînes de recherche de ligne de commande doivent être échappés avec une barre oblique inverse comme \". Cela est vrai pour les chaînes de recherche littérales et regex. Ces informations ont été confirmées sur XP, Vista et Windows 7.

Remarque: Le guillemet doit également être échappé pour l'analyseur CMD.EXE, mais cela n'a rien à voir avec FINDSTR. Par exemple, pour rechercher un devis unique, vous pouvez utiliser:

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

Échappement de la barre oblique inverse dans les chaînes de recherche littérale de ligne de commande La barre oblique
inverse dans une chaîne de recherche littérale peut normalement être représentée sous la forme \ou sous la forme \\. Ils sont généralement équivalents. (Il peut y avoir des cas inhabituels dans Vista où la barre oblique inverse doit toujours être échappée, mais je n'ai plus de machine Vista à tester) .

Mais il existe des cas particuliers:

Lors de la recherche de barres obliques inverses consécutives, tous, sauf le dernier, doivent être échappés. La dernière barre oblique inverse peut éventuellement être échappée.

  • \\peut être codé comme \\\ou\\\\
  • \\\peut être codé comme \\\\\ou\\\\\\

Rechercher une ou plusieurs barres obliques inverses avant un devis est bizarre. La logique suggérerait que le guillemet doit être échappé et que chacune des barres obliques inverses principales devrait être échappée, mais cela ne fonctionne pas! Au lieu de cela, chacune des barres obliques inverses doit être double échappée et le guillemet est échappé normalement:

  • \" doit être codé comme \\\\\"
  • \\" doit être codé comme \\\\\\\\\"

Comme indiqué précédemment, un ou plusieurs guillemets échappés peuvent également nécessiter l'échappement avec ^pour l'analyseur CMD

Les informations de cette section ont été confirmées sur XP et Windows 7.

Échappement de la barre oblique inverse dans les chaînes de recherche d'expression régulière de ligne de commande

  • Vista uniquement: la barre oblique inverse dans une expression régulière doit être soit double échappée comme \\\\, ou bien simple échappée dans un jeu de classes de caractères comme [\\]

  • XP et Windows 7: la barre oblique inverse dans une expression régulière peut toujours être représentée par [\\]. Il peut normalement être représenté par \\. Mais cela ne fonctionne jamais si la barre oblique inverse précède un guillemet échappé.

    Une ou plusieurs barres obliques inverses avant un guillemet échappé doivent être soit double échappées, soit codées comme [\\]

    • \"peut être codé comme \\\\\"ou[\\]\"
    • \\"peut être codé comme \\\\\\\\\"ou [\\][\\]\"ou\\[\\]\"

Échapper les
guillemets et les barres obliques inverses dans / G: FILE chaînes de recherche littérales Citations et barres obliques inverses autonomes dans un fichier de chaîne de recherche littérale spécifié par / G: le fichier n'a pas besoin d'être échappé, mais ils peuvent l'être.

"et \"sont équivalents.

\et \\sont équivalents.

Si l'intention est de trouver \\, au moins la barre oblique inverse de début doit être échappée. Les deux \\\et \\\\travailler.

Si l'intention est de trouver ", au moins la barre oblique inverse de début doit être échappée. Les deux \\"et \\\"fonctionnent.

Échappement de Quote et Backslash dans / G: FILE chaînes de recherche de regex
C'est le seul cas où les séquences d'échappement fonctionnent comme prévu d'après la documentation. Quote n'est pas un métacaractère regex, il n'a donc pas besoin d'être échappé (mais peut l'être). Backslash est un métacaractère regex, il doit donc être échappé.

Limites de caractères pour les paramètres de ligne de commande - Transformation ASCII étendue
Le caractère nul (0x00) ne peut apparaître dans aucune chaîne de la ligne de commande. Tout autre caractère à un octet peut apparaître dans la chaîne (0x01 - 0xFF). Cependant, FINDSTR convertit de nombreux caractères ASCII étendus qu'il trouve dans les paramètres de ligne de commande en d'autres caractères. Cela a un impact majeur de deux manières:

  1. De nombreux caractères ASCII étendus ne correspondent pas s'ils sont utilisés comme chaîne de recherche sur la ligne de commande. Cette limitation est la même pour les recherches littérales et regex. Si une chaîne de recherche doit contenir de l'ASCII étendu, l' /G:FILEoption doit être utilisée à la place.

  2. FINDSTR peut ne pas trouver un fichier si le nom contient des caractères ASCII étendus et que le nom du fichier est spécifié sur la ligne de commande. Si un fichier à rechercher contient de l'ASCII étendu dans le nom, l' /F:FILEoption doit être utilisée à la place.

Voici une liste complète des transformations de caractères ASCII étendues que FINDSTR effectue sur les chaînes de ligne de commande. Chaque caractère est représenté comme la valeur de code d'octet décimal. Le premier code représente le caractère tel qu'il est fourni sur la ligne de commande et le deuxième code représente le caractère dans lequel il est transformé. Remarque - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

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

Tout caractère> 0 ne figurant pas dans la liste ci-dessus est traité comme lui-même, y compris <CR>et < LF>. Le moyen le plus simple d'inclure des caractères impairs comme <CR>et <LF>est de les placer dans une variable d'environnement et d'utiliser l'expansion retardée dans l'argument de ligne de commande.

Limites de caractères pour les chaînes trouvées dans les fichiers spécifiés par les options / G: FILE et / F: FILE
Le caractère nul (0x00) peut apparaître dans le fichier, mais il fonctionne comme le terminateur de chaîne C. Tous les caractères après un caractère nul sont traités comme une chaîne différente comme s'ils se trouvaient sur une autre ligne.

Les caractères <CR>et <LF>sont traités comme des terminateurs de ligne qui terminent une chaîne et ne sont pas inclus dans la chaîne.

Tous les autres caractères à un octet sont parfaitement inclus dans une chaîne.

Recherche de fichiers Unicode
FINDSTR ne peut pas rechercher correctement la plupart des Unicode (UTF-16, UTF-16LE, UTF-16BE, UTF-32) car il ne peut pas rechercher d'octets nuls et Unicode contient généralement de nombreux octets nuls.

Cependant, la commande TYPE convertit UTF-16LE avec BOM en un jeu de caractères à un octet, donc une commande comme celle-ci fonctionnera avec UTF-16LE avec BOM.

type unicode.txt|findstr "search"

Notez que les points de code Unicode qui ne sont pas pris en charge par votre page de codes active seront convertis en ?caractères.

Il est possible de rechercher UTF-8 tant que votre chaîne de recherche ne contient que de l'ASCII. Cependant, la sortie de console de tout caractère UTF-8 multi-octets ne sera pas correcte. Mais si vous redirigez la sortie vers un fichier, le résultat sera correctement encodé en UTF-8. Notez que si le fichier UTF-8 contient une nomenclature, alors la nomenclature sera considérée comme faisant partie de la première ligne, ce qui pourrait annuler une recherche qui correspond au début d'une ligne.

Il est possible de rechercher des caractères UTF-8 multi-octets si vous placez votre chaîne de recherche dans un fichier de recherche encodé en UTF-8 (sans BOM) et utilisez l'option / G.

Fin de ligne
FINDSTR coupe les lignes immédiatement après chaque <LF>. La présence ou l'absence de <CR> n'a aucun impact sur les sauts de ligne.

Recherche à travers les sauts de ligne
Comme prévu, le .métacaractère regex ne correspondra pas à <CR> ou <LF>. Mais il est possible d'effectuer une recherche sur un saut de ligne à l'aide d'une chaîne de recherche en ligne de commande. Les caractères <CR> et <LF> doivent être mis en correspondance explicitement. Si une correspondance multiligne est trouvée, seule la 1ère ligne de la correspondance est imprimée. FINDSTR revient ensuite à la deuxième ligne de la source et recommence la recherche - une sorte de fonction de type «regarder en avant».

Supposons que TEXT.TXT a ce contenu (peut être de style Unix ou Windows)

A
A
A
B
A
A

Puis ce 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

donne ces résultats

1:A
2:A
5:A

La recherche à travers les sauts de ligne à l'aide de l'option / G: FILE est imprécise car le seul moyen de faire correspondre <CR> ou <LF> est via une expression de plage de classe de caractères regex qui prend en sandwich les caractères EOL.

  • [<TAB>-<0x0B>] correspond à <LF>, mais correspond également à <TAB> et <0x0B>

  • [<0x0C>-!] correspond à <CR>, mais aussi à <0x0C> et!

Remarque - ce qui précède sont des représentations symboliques du flux d'octets regex car je ne peux pas représenter graphiquement les caractères.

Réponse suite à la partie 2 ci-dessous ...

Dbenham
la source
48
Exhaustivité exceptionnelle. Si seulement toutes les réponses sur Internet étaient comme ça.
Mike Viens
1
nous avons rencontré un problème avec addpath.batde Q141344 et findstr, qui peut être lié au problème de blocage de Win7 mentionné ci-dessus. J'ai créé une salle de chat pour essayer de retracer cela, pour tous ceux qui sont intéressés: chat.stackoverflow.com/rooms/13177/…
matt wilkie
2
EDIT - Affichage décrit des caractères de contrôle sous forme de points sur XP. Également documenté des bogues /Set des /Doptions provenant de noms de fichiers 8.3 courts.
dbenham
1
EDIT - 1) Les noms de fichier dans le fichier spécifié par / F: FILE ne doivent pas être entre guillemets. 2) La transformation des caractères ASCII étendus affecte à la fois les chaînes de recherche et les noms de fichiers lorsqu'ils sont fournis sur la ligne de commande.
dbenham
1
EDIT - Ajout d'un bug où la dernière ligne d'entrée canalisée est ignorée si elle se compose d'un seul caractère sans<LF>
dbenham
65

Réponse suite de la partie 1 ci - dessus - J'ai rencontré la limite de réponse de 30000 caractères :-(

Prise en
charge limitée des expressions régulières (regex) La prise en charge par FINDSTR des expressions régulières est extrêmement limitée. S'il ne figure pas dans la documentation HELP, il n'est pas pris en charge.

Au-delà de cela, les expressions regex prises en charge sont implémentées de manière totalement non standard, de sorte que les résultats peuvent être différents de ceux attendus de quelque chose comme grep ou perl.

Les ancres de position de ligne d'expression régulière ^ et $
^ correspondent au début du flux d'entrée ainsi qu'à toute position suivant immédiatement un <LF>. Puisque FINDSTR coupe également les lignes après <LF>, une simple expression régulière de "^" correspondra toujours à toutes les lignes d'un fichier, même un fichier binaire.

$correspond à n'importe quelle position précédant immédiatement un <CR>. Cela signifie qu'une chaîne de recherche regex contenant $ne correspondra jamais à aucune ligne dans un fichier texte de style Unix, ni à la dernière ligne d'un fichier texte Windows s'il manque le marqueur EOL de <CR> <LF>.

Remarque - Comme indiqué précédemment, des entrées canalisées et redirigées vers FINDSTR peuvent avoir été <CR><LF>ajoutées qui ne sont pas dans la source. Évidemment, cela peut avoir un impact sur une recherche regex qui utilise $.

Toute chaîne de recherche avec des caractères avant ^ou après $échouera toujours à trouver une correspondance.

Options de position / B / E / X
Les options de position fonctionnent de la même manière que ^et $, sauf qu'elles fonctionnent également pour les chaînes de recherche littérales.

/ B fonctionne de la même manière ^qu'au début d'une chaîne de recherche regex.

/ E fonctionne de la même manière $qu'à la fin d'une chaîne de recherche regex.

/ X fonctionne de la même manière que d'avoir ^à la fois au début et $à la fin d'une chaîne de recherche regex.

La limite du mot Regex
\< doit être le tout premier terme de l'expression régulière. Le regex ne correspondra à rien si d'autres caractères le précèdent. \<correspond soit au tout début de l'entrée, au début d'une ligne (la position immédiatement après un <LF>), soit à la position immédiatement après tout caractère "non-mot". Le caractère suivant n'a pas besoin d'être un caractère "mot".

\>doit être le tout dernier terme de l'expression régulière. Le regex ne correspondra à rien si d'autres caractères le suivent. \>correspond soit à la fin de l'entrée, soit à la position immédiatement avant un <CR>, soit à la position précédant immédiatement tout caractère "non-mot". Le caractère précédent n'a pas besoin d'être un caractère "mot".

Voici une liste complète des caractères "non-mot", représentés par le code d'octet décimal. Remarque - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

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

Plages de classes de caractères Regex [xy]
Les plages de classes de caractères ne fonctionnent pas comme prévu. Voir cette question: Pourquoi findstr ne gère-t-il pas correctement la casse (dans certaines circonstances)? , avec cette réponse: https://stackoverflow.com/a/8767815/1012053 .

Le problème est que FINDSTR ne rassemble pas les caractères par leur valeur de code d'octet (généralement considéré comme le code ASCII, mais ASCII n'est défini que de 0x00 à 0x7F). La plupart des implémentations de regex traiteraient [AZ] comme toutes les majuscules anglaises majuscules. Mais FINDSTR utilise une séquence de classement qui correspond à peu près au fonctionnement de SORT. Ainsi, [AZ] comprend l'alphabet anglais complet, en majuscules et minuscules (sauf pour "a"), ainsi que les caractères alpha non anglais avec des signes diacritiques.

Vous trouverez ci-dessous une liste complète de tous les caractères pris en charge par FINDSTR, triés dans la séquence de classement utilisée par FINDSTR pour établir des plages de classes de caractères regex. Les caractères sont représentés par leur valeur de code d'octet décimal. Je pense que la séquence de classement a le plus de sens si les caractères sont affichés à l'aide de la page de codes 437. Remarque - cette liste a été compilée sur une machine américaine. Je ne sais pas quel impact d'autres langues peuvent avoir sur cette liste.

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 termes de classe de caractères Regex et BUG
Non seulement FINDSTR est limité à un maximum de 15 termes de classe de caractères dans une expression régulière, mais il ne parvient pas à gérer correctement une tentative de dépassement de la limite. L'utilisation de termes de classe de 16 caractères ou plus entraîne une fenêtre contextuelle Windows interactive indiquant "L'utilitaire de recherche de chaîne (QGREP) a rencontré un problème et doit fermer. Nous sommes désolés pour le désagrément." Le texte du message varie légèrement selon la version de Windows. Voici un exemple de FINDSTR qui échouera:

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]

Ce bug a été signalé par l' utilisateur DosTips Judago ici . Il a été confirmé sur XP, Vista et Windows 7.


Les recherches regex échouent (et peuvent se bloquer indéfiniment) si elles incluent le code d'octet 0xFF (décimal 255) Toute recherche d'expression régulière qui inclut le code d'octet 0xFF (décimal 255) échouera. Il échoue si le code d'octet 0xFF est inclus directement ou s'il est implicitement inclus dans une plage de classes de caractères. N'oubliez pas que les plages de classes de caractères FINDSTR ne rassemblent pas les caractères en fonction de la valeur du code d'octet. Le caractère <0xFF>apparaît relativement tôt dans la séquence de classement entre les caractères <space>et <tab>. Donc, toute plage de classes de caractères qui inclut les deux <space>et <tab>échouera.

Le comportement exact change légèrement selon la version de Windows. Windows 7 se bloque indéfiniment si 0xFF est inclus. XP ne se bloque pas, mais il ne parvient toujours pas à trouver une correspondance et imprime parfois le message d'erreur suivant - "Le processus a essayé d'écrire dans un tube inexistant."

Je n'ai plus accès à une machine Vista, donc je n'ai pas pu tester sur Vista.

Bug Regex: .et [^anySet]peut correspondre à End-Of-File
Le .méta-caractère regex ne doit correspondre qu'à n'importe quel caractère autre que <CR>ou <LF>. Il existe un bogue qui lui permet de correspondre à la fin du fichier si la dernière ligne du fichier ne se termine pas par <CR>ou <LF>. Cependant, le .ne correspondra pas à un fichier vide.

Par exemple, un fichier nommé "test.txt" contenant une seule ligne de x, sans terminer <CR>ou <LF>, correspondra à ce qui suit:

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

Ce bogue a été confirmé sur XP et Win7.

La même chose semble être vraie pour les jeux de caractères négatifs. Quelque chose comme [^abc]cela correspondra à la fin du fichier. Les jeux de caractères positifs [abc]semblent fonctionner correctement. Je n'ai testé cela que sur Win7.

Dbenham
la source
1
findstr est également bogué avec des fichiers volumineux. Les fichiers> 2 Go peuvent entraîner le blocage de findstr. Cela n'arrive pas toujours. En confirmant le bogue, j'ai recherché un fichier de 2,3 Go qui ne se bloquait pas. Il se bloque même si vous recherchez un seul fichier. La solution de contournement consiste à canaliser la sortie de typedans findstr.
Désillusionné le
Il est probablement également intéressant de mentionner explicitement qu'il findstrprend en charge plusieurs /c:chaînes de recherche. Je sais que vos réponses le démontrent. Mais c'est quelque chose qui n'est pas documenté; et j'ai été assez surpris d'apprendre la fonctionnalité après l'avoir utilisée findstrsans elle pendant quelques années.
Déçu le
@CraigYoung - Vous avez raison sur les sources de chaînes de recherche. J'ai édité ma réponse, merci.
dbenham
1
Après une enquête plus approfondie, cela ressemble à une variante du LFproblème que vous avez documenté. J'ai réalisé que mon fichier de test ne se terminait pas LFparce que je l'ai utilisé copyen mode ajout pour le créer. J'ai mis une session de ligne de commande pour démontrer le problème dans une réponse ( stackoverflow.com/a/22943056/224704 ). Notez que l'entrée n'est pas redirigée, et pourtant la recherche se bloque. La même commande de recherche ne se bloque pas avec des fichiers plus petits qui ne se terminent pas non plus par LF.
Désillusionné le
1
Nouvelle découverte (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 caractères) - ErrorLevel = -1073740791 (0xC0000409), la fenêtre de dialogue d'erreur : Find String (QGREP) Utility has stopped working; après avoir supprimé une classe ou deux méta caractères ( *\.), ça marche ...
aschipfl
7

findstr se bloque parfois de manière inattendue lors de la recherche de fichiers volumineux.

Je n'ai pas confirmé les conditions exactes ou les tailles des limites. Je soupçonne que tout fichier de plus de 2 Go peut être à risque.

J'ai eu des expériences mitigées avec cela, donc c'est plus que juste la taille du fichier. Cela semble être une variante de FINDSTR se bloque sur XP et Windows 7 si l'entrée redirigée ne se termine pas par LF , mais comme démontré, ce problème particulier se manifeste lorsque l'entrée n'est pas redirigée.

La session de ligne de commande suivante (Windows 7) montre comment findstrse bloquer lors de la recherche d'un fichier de 3 Go.

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>

Remarque, j'ai vérifié dans un éditeur hexadécimal que toutes les lignes se terminent par CRLF. La seule anomalie est que le fichier se termine en 0x1Araison de la façon dont copyfonctionne . Notez cependant que cette anomalie ne pose pas de problème sur les "petits" fichiers .

Avec des tests supplémentaires, j'ai confirmé ce qui suit:

  • L'utilisation copyavec l' /boption pour les fichiers binaires empêche l'ajout du 0x1Acaractère et findstrne se bloque pas sur le fichier de 3 Go.
  • La terminaison du fichier de 3 Go avec un caractère différent entraîne également le findstrblocage d'un.
  • Le 0x1Acaractère ne pose aucun problème sur un "petit" fichier. (De même pour les autres caractères de fin.)
  • L'ajout CRLFaprès 0x1Arésout le problème. ( LFen soi suffirait probablement.)
  • Utilisation typepour diriger le fichier dans des findstrœuvres sans accrocher. (Cela peut être dû à un effet secondaire de l'un typeou l' autre ou |qui insère une fin de ligne supplémentaire.)
  • Utiliser une entrée redirigée <provoque également un findstrblocage. Mais cela est attendu; comme expliqué dans le post de dbenham : "l'entrée redirigée doit se terminer par LF" .
Désabusé
la source
1
+1, je suis en mesure de confirmer le problème sur ma machine Win7. Un fichier d'une taille exactement de 2 Go s'est bloqué alors que le dernier caractère ne l'était pas <LF>. Un fichier de deux octets plus petit ne s'est pas bloqué. Très sale!
dbenham
7

Lorsque plusieurs commandes sont placées entre parenthèses et qu'il y a des fichiers redirigés vers le bloc entier:

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

... alors les fichiers restent ouverts tant que les commandes du bloc sont actives, de sorte que les commandes peuvent déplacer le pointeur de fichier des fichiers redirigés. Les commandes MORE et FIND déplacent le pointeur de fichier Stdin au début du fichier avant de le traiter, de sorte que le même fichier peut être traité plusieurs fois à l'intérieur du bloc. Par exemple, ce code:

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

... produisent le même résultat que celui-ci:

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

Ce code:

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

... produisent le même résultat que celui-ci:

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

FINDSTR est différent; il ne déplace pas le pointeur de fichier Stdin de sa position actuelle. Par exemple, ce code insère une nouvelle ligne après une ligne de recherche:

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

Nous pouvons faire bon usage de cette fonctionnalité à l'aide d'un programme auxiliaire qui nous permet de déplacer le pointeur de fichier d'un fichier redirigé, comme indiqué dans cet exemple .

Ce comportement a été signalé pour la première fois par jeb à ce poste .


EDIT 2018-08-18 : Nouveau bogue FINDSTR signalé

La commande FINDSTR a un bogue étrange qui se produit lorsque cette commande est utilisée pour afficher des caractères en couleur ET que la sortie d'une telle commande est redirigée vers le périphérique CON. Pour plus d'informations sur l'utilisation de la commande FINDSTR pour afficher le texte en couleur, consultez cette rubrique .

Lorsque la sortie de cette forme de commande FINDSTR est redirigée vers CON, quelque chose d'étrange se produit après la sortie du texte dans la couleur désirée: tout le texte après qu'il est sorti en tant que caractères "invisibles", bien qu'une description plus précise soit que le texte est sortie sous forme de texte noir sur fond noir. Le texte d'origine apparaîtra si vous utilisez la commande COULEUR pour réinitialiser les couleurs de premier plan et d'arrière-plan de tout l'écran. Cependant, lorsque le texte est «invisible», nous pouvons exécuter une commande SET / P, de sorte que tous les caractères saisis n'apparaissent pas à l'écran. Ce comportement peut être utilisé pour saisir des mots de passe.

@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%"
Aacini
la source
2

Je voudrais signaler un bug concernant la section Source des données à rechercher dans la première réponse lorsque vous utilisez en dash (-) ou em dash (-) dans le nom de fichier.

Plus précisément, si vous êtes sur le point d'utiliser la première option - les noms de fichiers spécifiés comme arguments , le fichier ne sera pas trouvé. Dès que vous utilisez l'option 2 - stdin via la redirection ou 3 - flux de données à partir d'un tube , findstr trouvera le fichier.

Par exemple, ce simple script batch:

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

imprimera:

Nom de fichier avec un tiret:

  1. Comme argument
    FINDSTR: Impossible d'ouvrir le nom de fichier avec - dash.txt

  2. En tant que stdin via la redirection,
    je suis le fichier avec un tiret en.

  3. En tant que flux de données à partir d'un tuyau
    je suis le fichier avec un tiret en.

Nom de fichier avec tiret em:

  1. Comme argument
    FINDSTR: Impossible d'ouvrir le nom de fichier avec - dash.txt

  2. En tant que stdin via la redirection
    je suis le fichier avec un tiret em.

  3. En tant que flux de données à partir d'un tuyau
    je suis le fichier avec un tiret em.

J'espère que cela aide.

M.

matro
la source
1
Salut matro, bien que vos commentaires soient corrects, je ne suis pas sûr qu'ils ne répondent pas à la question réelle.
Wai Ha Lee
Je pense qu'il s'agit d'un problème Unicode, que FINDSTR ne prend pas en charge. La redirection CMD.EXE peut ouvrir correctement un nom de fichier avec unicode, tout comme la commande TYPE. Mais quelque part le long de la ligne, FINDSTR convertit à la fois le tiret en-ligne et le tiret em en un tiret normal, et bien sûr, le système d'exploitation ne peut pas trouver ce nom. Si vous créez un autre fichier en remplaçant un tiret pour le en-dash et / ou em-dash, alors FINDSTR recherchera le fichier de tiret s'il est fourni avec un nom contenant en-dash ou em-dash.
dbenham
Je classerais ce problème comme une limitation plutôt que comme un bogue.
dbenham
En fait, ce n'est pas tant un problème Unicode que l'ASCII étendu. J'ai déjà documenté ce problème dans ma réponse originale sous le titre Limites de caractères pour les paramètres de ligne de commande - Transformation ASCII étendue . FINDSTR transforme un certain nombre de codes ASCII étendus en véritables ASCII "associés", y compris le tiret en et le tiret en em.
dbenham
2

La findstrcommande définit le ErrorLevel(ou le code de sortie) sur l'une des valeurs suivantes, étant donné qu'il n'y a pas de commutateurs invalides ou incompatibles et qu'aucune chaîne de recherche ne dépasse la limite de longueur applicable:

  • 0 lorsqu'au moins une seule correspondance est rencontrée sur une ligne dans tous les fichiers spécifiés;
  • 1 autrement;

Une ligne est considérée comme contenant une correspondance lorsque:

  • non /V option n'est donnée et l'expression de recherche se produit au moins une fois;
  • l' /Voption est donnée et l'expression de recherche ne se produit pas;

Cela signifie que l' /Voption modifie également la valeur renvoyée ErrorLevel, mais elle ne le fait pas rétablit seulement!

Par exemple, lorsque vous avez un fichier test.txtavec deux lignes, dont l'une contient la chaîne textmais l'autre pas, les deux findstr "text" "test.txt"et findstr /V "text" "test.txt"retourne un ErrorLevelde0 .

En gros, vous pouvez dire: si findstrrenvoie au moins une ligne, ErrorLevelest défini sur 0, sinon sur1 .

Notez que l' /Moption n'affecte pas leErrorLevel valeur, elle modifie simplement la sortie.

(Juste pour être complet: la findcommande se comporte exactement de la même manière par rapport à l' /Voption et ErrorLevel; l' /Coption n'affecte pas ErrorLevel.)

aschipfl
la source
2

FINDSTR a un bug de couleur que j'ai décrit et résolu à /superuser/1535810/is-there-a-better-way-to-mitigate-this-obscure-color-bug-when-piping-to -findstr / 1538802? noredirect = 1 # comment2339443_1538802

Pour résumer ce thread, le bogue est que si l'entrée est dirigée vers FINDSTR dans un bloc de code entre parenthèses, les codes de couleur d'échappement ANSI en ligne cessent de fonctionner dans les commandes exécutées plus tard. Un exemple de codes de couleur en ligne est:echo %magenta%Alert: Something bad happened%yellow% couleur en (où le magenta et le jaune sont des variables définies plus tôt dans le fichier .bat comme codes de couleur d'échappement ANSI correspondants).

Ma solution initiale était d'appeler un sous-programme ne rien faire après le FINDSTR. D'une manière ou d'une autre, l'appel ou le retour "réinitialise" tout ce qui doit être réinitialisé.

Plus tard, j'ai découvert une autre solution qui est probablement plus efficace: placez la phrase FINDSTR entre parenthèses, comme dans l'exemple suivant: echo success | ( FINDSTR /R success ) Placer la phrase FINDSTR dans un bloc de code imbriqué semble isoler le bogue du code de couleur de FINDSTR afin qu'il n'affecte pas ce qui est en dehors de l'imbrication bloquer. Peut-être que cette technique résoudra également d'autres effets secondaires indésirables de FINDSTR .

Dolores Stevens
la source
Super trouvaille. Mais vos règles peuvent être simplifiées (au moins sur ma machine Windows 10 d'entreprise). FINDSTR empêche toutes les séquences d'échappement de console de fonctionner pour les commandes suivantes dans le même bloc de commandes. Peu importe si FINDSTR lit un tube, une entrée redirigée ou un fichier. L'échec de la séquence d'échappement n'est pas limité aux codes de couleur. Un bloc de commande est tout ensemble de commandes entre parenthèses et / ou commandes concaténées via &, &&, ou ||
dbenham le
@dbenham: Belle généralisation du problème. Savez-vous si ma solution - imbriquer la phrase FINDSTR entre parenthèses - fonctionne également dans le cas général? Et savez-vous si ma solution a des effets secondaires indésirables?
Dolores Stevens le
Je n'ai pas fait de tests exhaustifs, mais oui, les parenthèses imbriquées semblent être une solution générale, et je ne peux penser à aucun effet secondaire indésirable possible.
dbenham le
-1

/ D Astuce pour plusieurs répertoires: placez votre liste de répertoires avant la chaîne de recherche. Tout cela fonctionne:

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

Comme prévu, le chemin est relatif à l'emplacement si vous ne démarrez pas les répertoires avec \. Entourer le chemin avec "est facultatif s'il n'y a pas d'espaces dans les noms de répertoire. La fin \est facultative. La sortie de l'emplacement inclura le chemin que vous lui donnez. Cela fonctionnera avec ou sans entourer la liste des répertoires avec ".

Gordon
la source
Je ne vois rien de non documenté ici. L'option / D est décrite dans l'aide intégrée. Ce n'est pas une question pour obtenir des conseils généraux sur la façon d'utiliser FINDSTR. Il est strictement destiné à répertorier les fonctionnalités, limitations et / ou bogues non documentés.
dbenham
1
@dbenham est vrai que ce n'est pas vraiment non documenté, mais j'ai trouvé que je devais me débrouiller avec findstr pour obtenir les résultats que je voulais et que je partage ce que j'ai trouvé DID fonctionne pour que les gens ne perdent pas de temps à expérimenter des commandes qui ne fonctionnent PAS. hth (je suis triste que vous n'aimiez pas ma contribution - elle était uniquement destinée à être constructive)
gordon
IMHO le commutateur / D est clairement décrit dans l'aide intégrée: /D:dirlist Search a semicolon-delimited list of directorieset il est placé avant la chaîne de recherche, donc je ne comprends pas exactement ce que "vous avez trouvé" sur le commutateur / D (et quelles sont les "commandes qui ne fonctionne PAS ") ...
Aacini
@Aacini dans de nombreuses langues, l'ordre des attributs n'a pas d'importance. Je comprends d'abord la documentation de findstrlists / D. Oui, je n'ai aucun argument avec la fonctionnalité documentée, il n'est tout simplement pas documenté sur le fait que l'ordre des attributs compte. Je fais très peu de travail en ligne de commande, donc quand je bricolais une commande, ne sachant pas que l'ordre faisait une différence, j'ajoutais simplement les attributs au fur et à mesure que j'y arrivais (et par ordre alphabétique, C précède D). Je devenais vraiment frustré et j'ai partagé mon expérience "trouvée" pour quiconque ne travaille pas beaucoup avec la ligne de commande.
gordon
1
L'ordre des attributs facultatifs n'a généralement pas d'importance. La findstrdocumentation spécifie que la stringspartie n'est PAS facultative et que vous devez la placer après les attributs facultatifs et avant la liste de noms de fichiers facultative . Si "votre trouvé" est que l'utilisation d'une commande sans suivre son format d'utilisation provoque une erreur, alors un tel point est bien documenté. Voir la syntaxe de la commande : "La syntaxe apparaît dans l'ordre dans lequel vous devez taper une commande et tous les paramètres qui la suivent"
Aacini