Wie können Sie jede Zeile in einer Textdatei mithilfe einer Windows-Batchdatei durchlaufen?

244

Ich möchte wissen, wie man jede Zeile in einer Textdatei mit einer Windows-Batchdatei durchläuft und jede Textzeile nacheinander verarbeitet.

Herr Kraus
quelle

Antworten:

304

Die folgenden Beiträge haben sehr geholfen, aber nicht das getan, was ich in meiner Frage angegeben habe, wo ich die gesamte Zeile als Ganzes verarbeiten musste. Folgendes habe ich gefunden, um zu arbeiten.

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

Das Token-Schlüsselwort mit einem Sternchen (*) zieht den gesamten Text für die gesamte Zeile ab. Wenn Sie das Sternchen nicht eingeben, wird nur das erste Wort in der Zeile angezeigt. Ich nehme an, es hat mit Leerzeichen zu tun.

Für den Befehl im TechNet

Ich schätze alle Beiträge!


Wenn Ihr Dateipfad Leerzeichen enthält, müssen Sie diese verwenden usebackq. Beispielsweise.

for /F "usebackq tokens=*" %%A in ("my file.txt") do [process] %%A
Herr Kraus
quelle
37
Ein kleiner Zusatz: Damit dies über die Befehlszeile interaktiv funktioniert, ersetzen Sie es %%Adurch %Aden obigen Befehl. Sonst wirst du bekommen %%A was unexpected at this time..
Vadipp
16
Zu Ihrer Information, wenn Sie einen mehrzeiligen Befehl ausführen müssen, können Sie nach "DO" eine offene Klammer "(" und einige Zeilen später mit einer engen Klammer ")" einfügen - und Sie können einfach Ihren Code einfügen Block in diesen (nach Ihrem Geschmack eingerückt).
BrainSlugs83
3
Danke für dieses Muster. Ich habe festgestellt, dass ich den Dateinamen nicht in Anführungszeichen (") setzen kann - Bei Dateinamen mit Leerzeichen wird nur der Dateiname angegeben. ZB for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Irgendwelche Ideen, wie dies vereitelt werden kann?
wird der
1
Stellen Sie sicher, dass die Datei, an der Sie arbeiten, in ANSI oder UTF8 codiert ist. Ich kratzte mir am Kopf, warum dies nicht funktionierte, bis ich versuchte, die Datei mit dem Befehl TYPE anzuzeigen, und die Ausgabe nicht den Erwartungen entsprach. Zu diesem Zeitpunkt bemerkte ich, dass die Datei aus irgendeinem Grund in "UCS-2 BE BOM" codiert war!
Dan Stevens
1
Es ist erwähnenswert, dass der Indexparameter in Ihrer Schleife ein einzelnes Zeichen sein muss. Zum Beispiel ist %% i in Ordnung, aber der %% Index schlägt fehl.
Vincent
59

Aus der Windows-Befehlszeilenreferenz:

Geben Sie Folgendes ein, um eine Datei zu analysieren und kommentierte Zeilen zu ignorieren:

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

Dieser Befehl analysiert jede Zeile in Myfile.txt, ignoriert Zeilen, die mit einem Semikolon beginnen, und übergibt das zweite und dritte Token von jeder Zeile an den FOR-Body (Token werden durch Kommas oder Leerzeichen getrennt). Der Hauptteil der FOR-Anweisung verweist auf% i, um das zweite Token abzurufen,% j, um das dritte Token abzurufen, und% k, um alle verbleibenden Token abzurufen.

Wenn die von Ihnen angegebenen Dateinamen Leerzeichen enthalten, verwenden Sie Anführungszeichen um den Text (z. B. "Dateiname"). Um Anführungszeichen zu verwenden, müssen Sie usebackq verwenden. Andernfalls werden die Anführungszeichen so interpretiert, dass sie eine zu analysierende Literalzeichenfolge definieren.

Übrigens finden Sie die Befehlszeilen-Hilfedatei auf den meisten Windows-Systemen unter:

 "C:\WINDOWS\Help\ntcmds.chm"
Asche
quelle
8
zu klären , die „Anführungszeichen zu verwenden, müssen Sie verwenden usebackq : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus
35

In einer Batchdatei Sie MÜSSEN verwenden %%statt %: (Typ 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

Was dies bewirkt: Das "do call: process %% i %% j %% k" am Ende des for-Befehls übergibt die im for-Befehl von myfile.txt erfassten Informationen an die "process" -Unterroutine.

Wenn Sie den Befehl for in einem Stapelverarbeitungsprogramm verwenden, müssen Sie doppelte% -Zeichen für die Variablen verwenden.

In den folgenden Zeilen werden diese Variablen vom Befehl for an die Unterroutine des Prozesses übergeben, und Sie können diese Informationen verarbeiten.

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

Ich habe einige ziemlich fortgeschrittene Anwendungen dieses genauen Setups, die ich gerne teilen würde, wenn weitere Beispiele benötigt werden. Fügen Sie Ihre EOL oder Delims nach Bedarf hinzu.

user332474
quelle
27

Verbesserung der ersten "FOR / F .." - Antwort: Ich musste jedes in MyList.txt aufgelistete Skript ausführen, damit es für mich funktioniert:

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

- ODER, wenn Sie es über mehrere Zeilen tun möchten:

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

Bearbeiten: Das oben angegebene Beispiel dient zum Ausführen der FOR-Schleife an der Eingabeaufforderung. Aus einem Batch-Skript muss ein zusätzliches% hinzugefügt werden, wie unten gezeigt:

---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
quelle
21

@ MrKraus ' Antwort ist aufschlussreich . Lassen Sie mich außerdem hinzufügen, dass Sie dem Dateinamen% ~ dp0 voranstellen , wenn Sie eine Datei laden möchten, die sich im selben Verzeichnis wie die Batchdatei befindet. Hier ist ein Beispiel:

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

NB :: Wenn Ihr Dateiname oder Verzeichnis (z. B. myfile.txt im obigen Beispiel) ein Leerzeichen enthält (z. B. 'my file.txt' oder 'c: \ Programme'), verwenden Sie:

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

mit dem Schlüsselwort type , das das typeProgramm aufruft und den Inhalt einer Textdatei anzeigt. Wenn Sie nicht den Aufwand für den Aufruf des Befehls type erleiden möchten, sollten Sie das Verzeichnis in das Verzeichnis der Textdatei ändern. Beachten Sie, dass der Typ für Dateinamen mit Leerzeichen weiterhin erforderlich ist.

Ich hoffe das hilft jemandem!

Marvin Thobejane
quelle
Dem Dateinamen muss kein Präfix vorangestellt werden, da die Batchdatei standardmäßig im aktuellen Ordner angezeigt wird.
foxidrive
1
@foxidrive: Okay, ich höre dich. Obwohl Vorsicht geboten ist. Wenn beispielsweise ein Verzeichnis geändert würde, würde es in diesem Verzeichnis und nicht in dem Verzeichnis aussehen, in dem sich die Batchdatei befindet. Die Lösung würde dann **cd /d %~dp0**vor der for-Schleife aufrufen . Dies würde sicherstellen, dass Sie auf eine Datei in dem Verzeichnis verweisen, in dem sich die Batch-Datei befindet. Vielen Dank für die Beobachtung
Marvin Thobejane
2
Thx und +1 für den typeWalkaround
Halex
Ich kann die typeArbeit nicht zum Laufen bringen, ich musste meinen Dateinamen zitieren, weil er sich in einem anderen Verzeichnis befindet, das Leerzeichen enthält (Verdammt noch mal Program Files). Ich The system cannot find the file `type.
erhalte
1
@scragar, hast du das richtige Zitat? es muss ein "kein" sein. Auf meiner Tastatur ist es auf der gleichen Taste wie @
FrinkTheBrave
18

Die akzeptierte Antwort ist gut, hat aber zwei Einschränkungen.
Es werden leere Zeilen und Zeilen gelöscht, die mit beginnen;

Um Zeilen mit Inhalten lesen zu können, benötigen Sie die Technik zum Umschalten der verzögerten Erweiterung.

@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 wird verwendet, um jeder Zeile die Zeilennummer und einen Doppelpunkt voranzustellen, sodass leere Zeilen nicht mehr leer sind.

DelayedExpansion muss deaktiviert werden, wenn auf den %%aParameter !zugegriffen ^wird. Andernfalls gehen Ausrufezeichen und Carets verloren, da sie in diesem Modus eine besondere Bedeutung haben.

Um die Zeilennummer aus der Leitung zu entfernen, muss die verzögerte Erweiterung aktiviert werden.
set "var=!var:*:=!"Entfernt alle bis zum ersten Doppelpunkt (mit delims=:würde auch alle Doppelpunkte am Anfang einer Zeile entfernt, nicht nur der aus findstr).
Das Endlokal deaktiviert die verzögerte Erweiterung für die nächste Zeile erneut.

Die einzige Einschränkung ist jetzt die Zeilenlängenbeschränkung von ~ 8191, aber es scheint keine Möglichkeit zu geben, dies zu überwinden.

jeb
quelle
Win 10 erlaubt keine setlocalKommandozeile. Wenn ich Code auf CMD ausführe, erhalte ich! Var! statt Leerzeichen. Wie repariert man?
Zimba
Die Zeilenlängenbeschränkung kann überwunden werden, indem die Datei vor der Verarbeitung in temporäre Dateien mit einer maximalen Zeilenlänge von 8190 aufgeteilt wird. Dann zu einer Datei neu kombiniert.
Zimba
14

Oder Sie können die Optionen in Anführungszeichen ausschließen:

FOR /F %%i IN (myfile.txt) DO ECHO %%i
Paul
quelle
1
Zwei Prozentzeichen nebeneinander %% werden wie ein einzelnes Prozentzeichen in einem Befehl behandelt (keine Batchdatei).
Paul
9

Hier ist eine Bat-Datei, die ich geschrieben habe, um alle SQL-Skripte in einem Ordner auszuführen:

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

quelle
6

Wenn Sie eine NT-Familie von Windows (eines mit haben cmd.exeals Shell), versuchen Sie die FOR / F - Befehl .

Michael Ratanapintha
quelle
6

Die akzeptierte Antwort mit cmd.exeund

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

funktioniert nur für "normale" Dateien. Bei riesigen Dateien scheitert es kläglich.

Für große Dateien müssen Sie möglicherweise Powershell und Folgendes verwenden:

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

oder wenn Sie genug Speicher haben:

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

Dies funktionierte bei mir mit einer 250-MB-Datei mit über 2 Millionen Zeilen, bei der der for /F ...Befehl nach einigen tausend Zeilen hängen blieb.

Die Unterschiede zwischen foreachund ForEach-Objectfinden Sie unter Kennenlernen von ForEach und ForEach-Object .

(Credits: Datei zeilenweise in PowerShell lesen )

mivk
quelle
1

Modifizierte Beispiele hier, um unsere Rails-Apps auf Heroku aufzulisten - danke!

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

Vollständiger Code hier .

Sendbits
quelle
Per Kommentar zu einer anderen Frage oben - Sie können das Erstellen / Lesen von Dateien überspringen und einfach verwenden for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(Beachten Sie die Hinzufügung von ^'s, die zum Entweichen aus der Pipe verwendet werden, damit sie an den forund nicht direkt an den Befehlsprozessor übergeben werden)
user66001
0

So drucken Sie alle Zeilen in einer Textdatei über die Befehlszeile (mit verzögerter Erweiterung):

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!)

Funktioniert mit führenden Leerzeichen, Leerzeilen und Leerzeichen.

Getestet auf Win 10 CMD

Zimba
quelle
Gott versuche es, aber deine erste Probe entfernt führende ]]]Zeilen. Die zweite Probe lässt leere Linien und Linien fallen, die mit Leerzeichen beginnen
jeb
Die zweite soll Leerzeilen entfernen. 1. man könnte ändern, delimswenn irgendwelche Zeilen in der Textdatei mit ]z. durch ein Zeichen ersetzen, das dies nicht tut, oder durch ein Steuerzeichen wie Rücktaste oder Glocke; Sie werden normalerweise nicht in Textdateien gefunden. Der Grund delims=]ist Platzhalter erstellt entfernen /nvon findBefehlsleerzeilen zu bewahren.
Zimba
@jeb: Klammer]]] Problem behoben. Siehe Aktualisieren, um alle Zeilen in einer Textdatei zu drucken. Funktioniert auch unter Win 10 CMD.
Zimba