Come si fa a scorrere ogni riga in un file di testo utilizzando un file batch di Windows?


244

Vorrei sapere come eseguire il ciclo attraverso ogni riga di un file di testo utilizzando un file batch di Windows ed elaborare ciascuna riga di testo in successione.

Risposte:


305

I post di seguito sono stati di grande aiuto, ma non hanno fatto ciò che ho dichiarato nella mia domanda in cui dovevo elaborare l'intera riga nel suo insieme. Ecco cosa ho scoperto di funzionare.

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

La parola chiave token con un asterisco (*) estrarrà tutto il testo per l'intera riga. Se non si inserisce l'asterisco, verrà visualizzata solo la prima parola sulla riga. Presumo che abbia a che fare con gli spazi.

Per comando su TechNet

Apprezzo tutti i post!


Se ci sono spazi nel percorso del file, è necessario utilizzare usebackq. Per esempio.

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

37
Un'aggiunta minore: per fare in modo che questo funzioni dalla riga di comando in modo interattivo, sostituiscilo %%Acon %Ail comando sopra. Altrimenti otterrai %%A was unexpected at this time..
vadipp,

17
Cordiali saluti, se è necessario eseguire un comando multilinea, dopo "DO" è possibile inserire una parentesi aperta "(" e alcune righe dopo, terminarla con una parentesi chiusa ")" - e si può semplicemente inserire il codice blocco all'interno di quelli (rientrati ai tuoi gusti).
BrainSlugs83,

3
Grazie per quello schema. Ho scoperto che non riesco a mettere le virgolette (") attorno al nome del file - Per i nomi di file con spazi mi dà solo il nome del file. Ad esempio for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. Qualche idea su come contrastare questo?
sarà il

1
Assicurarsi che il file in uso sia codificato in ANSI o UTF8. Mi stavo grattando la testa sul motivo per cui non funzionava fino a quando non ho provato a visualizzare il file usando il comando TYPE e l'output non era quello che mi aspettavo. A questo punto ho notato che il file era stato codificato in "UCS-2 BE BOM" per qualche motivo!
Dan Stevens,

1
Vale la pena sottolineare che il parametro index nel tuo loop deve essere un singolo carattere. Ad esempio, %% i va bene, ma l'indice %% fallirà.
Vincent

59

Dal riferimento alla riga di comando di Windows:

Per analizzare un file, ignorando le righe commentate, digitare:

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

Questo comando analizza ogni riga in Myfile.txt, ignorando le righe che iniziano con un punto e virgola e passando il secondo e il terzo token da ciascuna riga al corpo FOR (i token sono delimitati da virgole o spazi). Il corpo dell'istruzione FOR fa riferimento a% i per ottenere il secondo token,% j per ottenere il terzo token e% k per ottenere tutti i token rimanenti.

Se i nomi dei file forniti contengono spazi, utilizzare le virgolette attorno al testo (ad esempio, "Nome file"). Per utilizzare le virgolette, è necessario utilizzare usebackq. In caso contrario, le virgolette vengono interpretate come definizione di una stringa letterale da analizzare.

A proposito, puoi trovare il file della guida della riga di comando sulla maggior parte dei sistemi Windows su:

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

8
per chiarire la "per usare le virgolette, è necessario utilizzare usebackq" : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

In un file batch DEVI usare %%invece di %: (Tipo 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

Cosa fa: Il "do call: process %% i %% j %% k" alla fine del comando for passa le informazioni acquisite nel comando for da myfile.txt alla "subroutine" "process".

Quando si utilizza il comando for in un programma batch, è necessario utilizzare il doppio segno% per le variabili.

Le seguenti righe passano quelle variabili dal comando for alla "sub routine" del processo e consentono di elaborare queste informazioni.

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

Ho alcuni usi piuttosto avanzati di questa configurazione esatta che sarei disposto a condividere se fossero necessari ulteriori esempi. Aggiungi la tua EOL o Delims, se necessario, ovviamente.


27

Migliorare la prima risposta "FOR / F ..": Quello che dovevo fare era chiamare eseguire ogni script elencato in MyList.txt, quindi ha funzionato per me:

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

--OPPURE, se si desidera farlo su più righe:

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

Modifica: l'esempio sopra riportato è per l'esecuzione del ciclo FOR dal prompt dei comandi; da uno script batch, è necessario aggiungere una% in più, come mostrato di seguito:

---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 risposta di MrKraus è istruttiva. Inoltre, vorrei aggiungere che se si desidera caricare un file situato nella stessa directory del file batch, aggiungere il prefisso al nome del file con% ~ dp0. Ecco un esempio:

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

NB:: Se il nome o la directory del tuo file (ad es. Myfile.txt nell'esempio sopra) ha uno spazio (ad es. "My file.txt" o "c: \ Programmi"), usa:

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

, con la parola chiave type che chiama il typeprogramma, che visualizza il contenuto di un file di testo. Se non si desidera subire il sovraccarico di chiamare il comando type, è necessario modificare la directory nella directory del file di testo. Si noti che il tipo è ancora richiesto per i nomi di file con spazi.

Spero che questo aiuti qualcuno!


Non è necessario aggiungere il prefisso al nome del file poiché il file batch verrà visualizzato nella cartella corrente per impostazione predefinita.
foxidrive,

1
@foxidrive: Ok, ti ​​sento. Anche se dovrebbe essere presa cura. Ad esempio, se una directory fosse cambiata, sembrerebbe in quella directory piuttosto che in quella in cui si trova il file batch. La soluzione sarebbe quindi chiamare **cd /d %~dp0**prima del ciclo for. Ciò assicurerebbe di fare riferimento a un file nella directory in cui si trova il file batch. Grazie per l'osservazione
Marvin Thobejane,

2
Grazie e +1 per il typewalkaround
halex

Non riesco a far typefunzionare il lavoro, ho dovuto citare il mio nome file perché si trova in una directory diversa che contiene spazi (Accidenti a te Program Files). Ricevo un erroreThe system cannot find the file `type.
scragar

1
@scragar, hai la citazione giusta? deve essere un 'non un'. Sulla mia tastiera è sullo stesso tasto di @
FrinkTheBrave il

18

La risposta accettata è buona, ma ha due limitazioni.
Elimina linee vuote e linee che iniziano con;

Per leggere righe di qualsiasi contenuto, è necessaria la tecnica di attivazione / disattivazione dell'espansione ritardata.

@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 viene utilizzato per aggiungere un prefisso a ciascuna riga con il numero di riga e i due punti, quindi le righe vuote non sono più vuote.

L'espansione ritardata deve essere disabilitata, quando si accede al %%aparametro, altrimenti i punti esclamativi !e i punti di inserimento ^andranno persi, poiché hanno significati speciali in quella modalità.

Ma per rimuovere il numero di riga dalla riga, è necessario abilitare l'espansione ritardata.
set "var=!var:*:=!"rimuove tutto fino ai primi due punti (usando delims=:rimuoveresti anche tutti i due punti all'inizio di una riga, non solo quello di findstr).
L'endlocal disabilita nuovamente l'espansione ritardata per la riga successiva.

L'unica limitazione è ora il limite di lunghezza della linea di ~ 8191, ma non sembra esserci modo di superarlo.


Win 10 non consente setlocalsulla riga di comando. Quando eseguo il codice su CMD, ottengo! Var! invece di spazi vuoti. Come risolvere?
Zimba,

il limite di lunghezza della linea può essere superato suddividendo il file in file temporanei di lunghezza massima della linea 8190 prima dell'elaborazione. Quindi ricombinato in un file.
Zimba,

14

Oppure, puoi escludere le opzioni tra virgolette:

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

1
I due segni di percentuale uno accanto all'altro %% sono trattati come un singolo segno di percentuale in un comando (non un file batch).
Paul,

9

Ecco un file bat che ho scritto per eseguire tutti gli script SQL in una cartella:

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 risposta accettata con cmd.exee

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

funziona solo per file "normali". Fallisce miseramente con file di grandi dimensioni.

Per file di grandi dimensioni, potrebbe essere necessario utilizzare Powershell e qualcosa del genere:

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

o se hai abbastanza memoria:

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

Questo ha funzionato per me con un file da 250 MB contenente oltre 2 milioni di righe, in cui il for /F ...comando si è bloccato dopo alcune migliaia di righe.

Per le differenze tra foreache ForEach-Object, vedere Informazioni su ForEach e ForEach-Object .

(crediti: leggi il file riga per riga in PowerShell )


1

Esempi modificati qui per elencare le nostre app Rails su Heroku - grazie!

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

Codice completo qui .


Per commento a un'altra domanda sopra - Puoi saltare la creazione / lettura del file e semplicemente usare for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...(Nota l'aggiunta di viene ^usata per uscire dalla pipe, in modo che venga passata al fore non direttamente al processore dei comandi)
user66001

0

Per stampare tutte le righe nel file di testo dalla riga di comando (con delayedExpansion):

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

Funziona con i principali spazi bianchi, linee vuote, linee di spazi bianchi.

Testato su Win 10 CMD


Dio ci provi, ma il tuo primo campione rimuove le ]]]linee guida dal primo , il secondo campione lascia linee vuote e linee che iniziano con lo spazio
jeb

Il secondo ha lo scopo di rimuovere le righe vuote. Il primo potrebbe essere modificato delimsse qualche riga nel file di testo inizia con ]es. sostituire con un personaggio che non lo fa, o un personaggio di controllo come backspace o bell; normalmente non si trovano nei file di testo. La ragione per delims=]è quello di eliminare i segnaposto creati dal /ndi findcomando per conservare righe vuote.
Zimba,

@jeb: parentesi]]] problema risolto. Vedi aggiornamento, per stampare tutte le righe nel file di testo. Funziona anche con Win 10 CMD.
Zimba,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.