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.

M. Kraus
la source

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
M. Kraus
la source
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"
Cendre
la source
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.

user332474
la source
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---
Yogesh Mahajan
la source
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!

Marvin Thobejane
la source
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.

jeb
la source
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
Paul
la source
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

la source
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 )

mivk
la source
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 .

sendbits
la source
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

Zimba
la source
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