Comment parcourez-vous chaque ligne d'un fichier texte à l'aide d'un fichier batch Windows?


244

Je voudrais savoir comment parcourir chaque ligne d'un fichier texte à l'aide d'un fichier de commandes Windows et traiter successivement chaque ligne de texte.

Réponses:


305

Les messages ci-dessous ont beaucoup aidé, mais n'ont pas fait ce que j'ai dit dans ma question, où je devais traiter la ligne entière dans son ensemble. Voici ce que j'ai trouvé à travailler.

for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

Le mot clé tokens avec un astérisque (*) tirera tout le texte de la ligne entière. Si vous ne mettez pas l'astérisque, il ne fera que tirer le premier mot sur la ligne. Je suppose que cela a à voir avec les espaces.

Pour la commande sur TechNet

J'apprécie tous les messages!


S'il y a des espaces dans votre chemin de fichier, vous devez utiliser usebackq. Par exemple.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A

37
Un ajout mineur: pour que cela fonctionne à partir de la ligne de commande de manière interactive, remplacez-le %%Apar %Adans la commande ci-dessus. Sinon, vous obtiendrez %%A was unexpected at this time..
vadipp

17
Pour info, si vous avez besoin de faire une commande sur plusieurs lignes, après "DO" vous pouvez mettre une parenthèse ouverte "(" et quelques lignes plus tard, terminez-la avec une parenthèse fermée ")" - et vous pouvez simplement mettre votre code bloquer à l'intérieur de ceux-ci (en retrait à vos goûts).
BrainSlugs83

3
Merci pour ce modèle. J'ai trouvé que je ne peux pas mettre de guillemets (") autour du nom de fichier - Pour les noms de fichiers avec des espaces, donne simplement le nom du fichier. Par exemple for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Des idées pour contrer cela?
le

1
Assurez-vous que le fichier que vous travaillez est codé en ANSI ou UTF8. Je me grattais la tête pour savoir pourquoi cela ne fonctionnait pas jusqu'à ce que j'essaie de visualiser le fichier à l'aide de la commande TYPE et que la sortie ne soit pas ce que j'attendais. À ce stade, j'ai remarqué que le fichier avait été encodé en "UCS-2 BE BOM" pour une raison quelconque!
Dan Stevens

1
Il convient de souligner que le paramètre d'index dans votre boucle doit être un seul caractère. Par exemple, %% i va bien, mais %% index échouera.
Vincent

59

À partir de la référence de la ligne de commande Windows:

Pour analyser un fichier, en ignorant les lignes commentées, tapez:

for /F "eol=; tokens=2,3* delims=," %i in (myfile.txt) do @echo %i %j %k

Cette commande analyse chaque ligne dans Myfile.txt, en ignorant les lignes qui commencent par un point-virgule et en passant les deuxième et troisième jetons de chaque ligne au corps FOR (les jetons sont délimités par des virgules ou des espaces). Le corps de l'instruction FOR fait référence à% i pour obtenir le deuxième jeton,% j pour obtenir le troisième jeton et% k pour obtenir tous les jetons restants.

Si les noms de fichiers que vous fournissez contiennent des espaces, utilisez des guillemets autour du texte (par exemple, "Nom de fichier"). Pour utiliser des guillemets, vous devez utiliser usebackq. Sinon, les guillemets sont interprétés comme définissant une chaîne littérale à analyser.

À propos, vous pouvez trouver le fichier d'aide en ligne de commande sur la plupart des systèmes Windows à l'adresse suivante:

 "C:\WINDOWS\Help\ntcmds.chm"

8
de clarifier la « d'utiliser des guillemets, vous devez utiliser usebackq» : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

Dans un fichier batch, vous DEVEZ utiliser à la %%place de %: (Type help for)

for /F "tokens=1,2,3" %%i in (myfile.txt) do call :process %%i %%j %%k
goto thenextstep
:process
set VAR1=%1
set VAR2=%2
set VAR3=%3
COMMANDS TO PROCESS INFORMATION
goto :EOF

Ce que cela fait: Le "do call: process %% i %% j %% k" à la fin de la commande for transmet les informations acquises dans la commande for de myfile.txt au "processus" "sous-programme".

Lorsque vous utilisez la commande for dans un programme batch, vous devez utiliser le double signe% pour les variables.

Les lignes suivantes transmettent ces variables de la commande for à la sous-routine du processus et vous permettent de traiter ces informations.

set VAR1=%1
 set VAR2=%2
 set VAR3=%3

J'ai quelques utilisations assez avancées de cette configuration exacte que je serais prêt à partager si d'autres exemples sont nécessaires. Ajoutez votre EOL ou Delims au besoin bien sûr.


27

Amélioration de la première réponse "FOR / F ..": Ce que je devais faire était d'appeler exécuter tous les scripts répertoriés dans MyList.txt, donc cela a fonctionné pour moi:

for /F "tokens=*" %A in  (MyList.txt) do CALL %A ARG1

--OU, si vous souhaitez le faire sur plusieurs lignes:

for /F "tokens=*" %A in  (MuList.txt) do (
ECHO Processing %A....
CALL %A ARG1
)

Edit: l'exemple donné ci-dessus est pour l'exécution de la boucle FOR à partir de l'invite de commande; à partir d'un script batch, un% supplémentaire doit être ajouté, comme indiqué ci-dessous:

---START of MyScript.bat---
@echo off
for /F "tokens=*" %%A in  ( MyList.TXT) do  (
   ECHO Processing %%A.... 
   CALL %%A ARG1 
)
@echo on
;---END of MyScript.bat---

21

@ La réponse de MrKraus est instructive. De plus, permettez-moi d'ajouter que si vous souhaitez charger un fichier situé dans le même répertoire que le fichier batch, préfixez le nom du fichier avec% ~ dp0. Voici un exemple:

cd /d %~dp0
for /F "tokens=*" %%A in (myfile.txt) do [process] %%A

NB: Si votre nom de fichier ou répertoire (par exemple monfichier.txt dans l'exemple ci-dessus) a un espace (par exemple 'mon fichier.txt' ou 'c: \ Program Files'), utilisez:

for /F "tokens=*" %%A in ('type "my file.txt"') do [process] %%A

, avec le mot-clé type appelant le typeprogramme, qui affiche le contenu d'un fichier texte. Si vous ne voulez pas subir la surcharge de l'appel de la commande type, vous devez remplacer le répertoire par le répertoire du fichier texte. Notez que le type est toujours requis pour les noms de fichiers avec des espaces.

J'espère que ça aidera quelqu'un!


Il n'est pas nécessaire de préfixer le nom du fichier car le fichier de commandes apparaîtra dans le dossier actuel par défaut.
foxidrive

1
@foxidrive: D'accord, je vous entends. Bien que des précautions soient prises. Par exemple, si un répertoire était modifié, il chercherait dans ce répertoire plutôt que dans celui dans lequel se trouve le fichier de commandes. La solution serait alors d'appeler **cd /d %~dp0**avant la boucle for. Cela garantirait que vous faites référence à un fichier dans le répertoire où se trouve le fichier batch. Merci pour l'observation
Marvin Thobejane

2
Thx et +1 pour le tour d' typehorizon
halex

Je ne peux pas faire typefonctionner le travail, j'ai dû citer mon nom de fichier car il se trouve dans un répertoire différent qui contient des espaces (Damn you Program Files). Je reçois une erreurThe system cannot find the file `type.
Scragar

1
@scragar, avez-vous le bon devis? ce doit être un «pas un». Sur mon clavier, c'est sur la même touche que @
FrinkTheBrave

18

La réponse acceptée est bonne, mais présente deux limites.
Il supprime les lignes vides et les lignes commençant par;

Pour lire des lignes de n'importe quel contenu, vous avez besoin de la technique de basculement d'extension retardée.

@echo off
SETLOCAL DisableDelayedExpansion
FOR /F "usebackq delims=" %%a in (`"findstr /n ^^ text.txt"`) do (
    set "var=%%a"
    SETLOCAL EnableDelayedExpansion
    set "var=!var:*:=!"
    echo(!var!
    ENDLOCAL
)

Findstr est utilisé pour préfixer chaque ligne avec le numéro de ligne et deux points, donc les lignes vides ne sont plus vides.

DelayedExpansion doit être désactivé, lors de l'accès au %%aparamètre, sinon les points d'exclamation !et les signes d'insertion ^seront perdus, car ils ont des significations spéciales dans ce mode.

Mais pour supprimer le numéro de ligne de la ligne, l'extension retardée doit être activée.
set "var=!var:*:=!"supprime tout jusqu'au premier deux-points (en utilisant delims=:supprimerait également tous les deux-points au début d'une ligne, pas seulement celui de findstr).
L'endlocal désactive à nouveau l'expansion retardée pour la ligne suivante.

La seule limitation est maintenant la limite de longueur de ligne de ~ 8191, mais il ne semble pas possible de surmonter cela.


Win 10 ne permet pas setlocalen ligne de commande. Lorsque j'exécute du code sur CMD, j'obtiens! Var! au lieu de blancs. Comment réparer?
Zimba

la limite de longueur de ligne peut être surmontée en divisant le fichier en fichiers temporaires d'une longueur de ligne maximale 8190 avant le traitement. Puis recombiné dans un fichier.
Zimba

14

Ou, vous pouvez exclure les options entre guillemets:

FOR /F %%i IN (myfile.txt) DO ECHO %%i

1
Les signes à deux pour cent côte à côte %% sont traités comme un signe à pourcentage unique dans une commande (pas un fichier de commandes).
Paul

9

Voici un fichier bat que j'ai écrit pour exécuter tous les scripts SQL dans un dossier:

REM ******************************************************************
REM Runs all *.sql scripts sorted by filename in the current folder.
REM To use integrated auth change -U <user> -P <password> to -E
REM ******************************************************************

dir /B /O:n *.sql > RunSqlScripts.tmp
for /F %%A in (RunSqlScripts.tmp) do osql -S (local) -d DEFAULT_DATABASE_NAME -U USERNAME_GOES_HERE -P PASSWORD_GOES_HERE -i %%A
del RunSqlScripts.tmp


6

La réponse acceptée en utilisant cmd.exeet

for /F "tokens=*" %F in (file.txt) do whatever "%F" ...

ne fonctionne que pour les fichiers "normaux". Il échoue lamentablement avec des fichiers énormes.

Pour les gros fichiers, vous devrez peut-être utiliser Powershell et quelque chose comme ceci:

[IO.File]::ReadLines("file.txt") | ForEach-Object { whatever "$_" }

ou si vous avez suffisamment de mémoire:

foreach($line in [System.IO.File]::ReadLines("file.txt")) { whatever "$line" } 

Cela a fonctionné pour moi avec un fichier de 250 Mo contenant plus de 2 millions de lignes, où la for /F ...commande s'est bloquée après quelques milliers de lignes.

Pour connaître les différences entre foreachet ForEach-Object, voir Présentation de ForEach et ForEach-Object .

(crédits: lire le fichier ligne par ligne dans PowerShell )


1

Exemples modifiés ici pour répertorier nos applications Rails sur Heroku - merci!

cmd /C "heroku list > heroku_apps.txt"
find /v "=" heroku_apps.txt | find /v ".TXT" | findstr /r /v /c:"^$" > heroku_apps_list.txt
for /F "tokens=1" %%i in (heroku_apps_list.txt) do heroku run bundle show rails --app %%i

Code complet ici .


Par commentaire à une autre question ci - dessus - Vous pouvez ignorer la création / lecture du fichier et simplement l'utiliser for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(notez l'ajout de ^'s utilisé pour échapper au tuyau, de sorte qu'il soit transmis au foret non directement au processeur de commandes)
user66001

0

Pour imprimer toutes les lignes du fichier texte à partir de la ligne de commande (avec une extension différée):

set input="path/to/file.txt"

for /f "tokens=* delims=[" %i in ('type "%input%" ^| find /v /n ""') do (
set a=%i
set a=!a:*]=]!
echo:!a:~1!)

Fonctionne avec les grands espaces, les lignes vides, les lignes des espaces.

Testé sur Win 10 CMD


Dieu essaie, mais votre premier échantillon supprime le début ]]]des lignes, le deuxième échantillon supprime les lignes vides et les lignes commençant par l'espace
jeb

Le 2ème est destiné à supprimer les lignes vides. Le premier pourrait être modifié delimssi des lignes du fichier texte commencent par ]ex. remplacer par un caractère qui ne le fait pas, ou un caractère de contrôle comme le retour arrière ou la cloche; ils ne se trouvent normalement pas dans les fichiers texte. La raison en delims=]est de supprimer les espaces réservés créés par la commande /nof findpour conserver les lignes vides.
Zimba

@jeb: bracket]]] problème résolu. Voir mise à jour, pour imprimer toutes les lignes dans un fichier texte. Fonctionne également sur Win 10 CMD.
Zimba
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.