¿Cómo recorre cada línea en un archivo de texto usando un archivo por lotes de Windows?


244

Me gustaría saber cómo recorrer cada línea en un archivo de texto usando un archivo por lotes de Windows y procesar cada línea de texto en sucesión.

Respuestas:


304

Las publicaciones a continuación ayudaron enormemente, pero no hicieron lo que dije en mi pregunta, donde necesitaba procesar toda la línea en su conjunto. Esto es lo que encontré para trabajar.

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

La palabra clave de tokens con un asterisco (*) extraerá todo el texto de toda la línea. Si no coloca el asterisco, solo extraerá la primera palabra de la línea. Supongo que tiene que ver con espacios.

Para comando en TechNet

Agradezco todas las publicaciones!


Si hay espacios en la ruta del archivo, debe usarlos usebackq. Por ejemplo.

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

37
Una adición menor: para hacer que esto funcione desde la línea de comandos de forma interactiva, reemplácelo %%Acon %Ael comando anterior. De lo contrario lo conseguirás %%A was unexpected at this time..
vadipp

16
Para su información, si necesita hacer un comando de varias líneas, después de "HACER" puede poner un paréntesis abierto "(" y algunas líneas más tarde, terminarlo con un paréntesis cerrado ")" - y simplemente puede poner su código bloquear dentro de esos (sangrado a su gusto).
BrainSlugs83

3
Gracias por ese patrón. He descubierto que no puedo poner comillas (") alrededor del nombre del archivo - Para los nombres de archivo con espacios solo me da el nombre del archivo. Ej. for /F "tokens=*" %%A in ("myfile.txt") do echo A = %%A-> A = myfile.txt. ¿Alguna idea de cómo frustrar esto?
será el

1
Asegúrese de que el archivo que está trabajando esté codificado en ANSI o UTF8. Me estaba rascando la cabeza por qué esto no funcionaba hasta que intenté ver el archivo usando el comando TIPO y la salida no era lo que esperaba. En este punto, ¡noté que el archivo había sido codificado en "UCS-2 BE BOM" por alguna razón!
Dan Stevens

1
Vale la pena señalar que el parámetro de índice en su ciclo debe ser un solo carácter. Entonces, por ejemplo, %% i está bien, pero el índice %% fallará.
Vincent

59

De la referencia de línea de comando de Windows:

Para analizar un archivo, ignorando las líneas comentadas, escriba:

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

Este comando analiza cada línea en Myfile.txt, ignorando las líneas que comienzan con un punto y coma y pasan el segundo y tercer token de cada línea al cuerpo FOR (los tokens están delimitados por comas o espacios). El cuerpo de la instrucción FOR hace referencia a% i para obtener el segundo token,% j para obtener el tercer token y% k para obtener todos los tokens restantes.

Si los nombres de archivo que proporciona contienen espacios, utilice comillas alrededor del texto (por ejemplo, "Nombre de archivo"). Para usar comillas, debe usar usebackq. De lo contrario, las comillas se interpretan como la definición de una cadena literal para analizar.

Por cierto, puede encontrar el archivo de ayuda de línea de comandos en la mayoría de los sistemas Windows en:

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

8
para aclarar el "usar comillas, debe utilizar usebackq" : for /f "usebackq" %%a in ("Z:\My Path Contains Spaces\xyz\abc.txt")
drzaus

35

En un archivo por lotes DEBE usar en %%lugar de %: (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

Qué hace esto: El "do call: process %% i %% j %% k" al final del comando for pasa la información adquirida en el comando for desde myfile.txt a la "subrutina" del proceso.

Cuando usa el comando for en un programa por lotes, debe usar signos de% doble para las variables.

Las siguientes líneas pasan esas variables del comando for al proceso 'subrutina' y le permiten procesar esta información.

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

Tengo algunos usos bastante avanzados de esta configuración exacta que estaría dispuesto a compartir si se necesitan más ejemplos. Agregue su EOL o Delims según sea necesario, por supuesto.


27

Mejorando la primera respuesta "FOR / F ..": Lo que tuve que hacer fue llamar a ejecutar cada script que figura en MyList.txt, por lo que funcionó para mí:

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

O bien, si desea hacerlo a través de la línea múltiple:

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

Editar: El ejemplo anterior es para ejecutar el bucle FOR desde el símbolo del sistema; desde un script por lotes, se debe agregar un% adicional, como se muestra a continuación:

---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 respuesta de @ MrKraus es instructiva. Además, permítame agregar que si desea cargar un archivo ubicado en el mismo directorio que el archivo por lotes, prefije el nombre del archivo con% ~ dp0. Aquí hay un ejemplo:

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

NB:: si su nombre de archivo o directorio (por ejemplo, myfile.txt en el ejemplo anterior) tiene un espacio (por ejemplo, 'mi archivo.txt' o 'c: \ Archivos de programa'), use:

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

, con la palabra clave type que llama al typeprograma, que muestra el contenido de un archivo de texto. Si no desea sufrir la sobrecarga de llamar al comando de tipo, debe cambiar el directorio al directorio del archivo de texto. Tenga en cuenta que el tipo aún es necesario para los nombres de archivos con espacios.

¡Espero que esto ayude a alguien!


No es necesario prefijar el nombre del archivo, ya que el archivo por lotes se verá en la carpeta actual de forma predeterminada.
foxidrive

1
@foxidrive: Bien, te escucho. Aunque se debe tener cuidado. Por ejemplo, si se cambiara un directorio, se vería en ese directorio en lugar de en el que está el archivo por lotes. La solución sería llamar **cd /d %~dp0**antes del ciclo for. Esto aseguraría que está haciendo referencia a un archivo en el directorio en el que se encuentra el archivo por lotes. Gracias por la observación
Marvin Thobejane

2
THX y 1 para el typewalkaround
Halex

No puedo typeevitar que funcione, tuve que citar mi nombre de archivo porque está en un directorio diferente que contiene espacios (Maldición Program Files). Recibo un errorThe system cannot find the file `type.
scragar

1
@scragar, ¿tienes la cita correcta? tiene que ser un "no un". En mi teclado está en la misma tecla que @
FrinkTheBrave

18

La respuesta aceptada es buena, pero tiene dos limitaciones.
Cae líneas vacías y líneas que comienzan con;

Para leer líneas de cualquier contenido, necesita la técnica de alternancia de expansión retrasada.

@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 se usa para prefijar cada línea con el número de línea y dos puntos, para que las líneas vacías ya no estén vacías.

DelayedExpansion debe deshabilitarse cuando se accede al %%aparámetro; de lo !contrario ^, se perderán los signos de exclamación y las marcas , ya que tienen significados especiales en ese modo.

Pero para eliminar el número de línea de la línea, la expansión demorada debe estar habilitada.
set "var=!var:*:=!"elimina todo hasta el primer colon (el uso delims=:eliminaría también todos los dos puntos al comienzo de una línea, no solo el de los hallazgos).
El endlocal desactiva la expansión demorada nuevamente para la siguiente línea.

La única limitación es ahora el límite de longitud de línea de ~ 8191, pero parece que no hay forma de superar esto.


Win 10 no permite setlocalen la línea de comandos. Cuando ejecuto código en CMD, obtengo! Var! en lugar de espacios en blanco. ¿Como arreglar?
Zimba

El límite de longitud de línea se puede superar dividiendo el archivo en archivos temporales de longitud máxima de línea 8190 antes del procesamiento. Luego recombinado a un archivo.
Zimba

14

O puede excluir las opciones entre comillas:

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

1
Dos signos de porcentaje uno al lado del otro %% se tratan como un signo de porcentaje único en un comando (no un archivo por lotes).
Paul

9

Aquí hay un archivo bat que escribí para ejecutar todos los scripts SQL en una carpeta:

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 respuesta aceptada usando cmd.exey

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

funciona solo para archivos "normales". Falla miserablemente con archivos enormes.

Para archivos grandes, puede que necesite usar Powershell y algo como esto:

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

o si tienes suficiente memoria:

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

Esto funcionó para mí con un archivo de 250 MB que contiene más de 2 millones de líneas, donde el for /F ...comando se atascó después de unos pocos miles de líneas.

Para conocer las diferencias entre foreachy ForEach-Object, consulte Introducción a ForEach y ForEach-Object .

(créditos: Leer archivo línea por línea en PowerShell )


1

Ejemplos modificados aquí para enumerar nuestras aplicaciones Rails en Heroku, ¡gracias!

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

Código completo aquí .


Por comentario a otra pregunta anterior : puede omitir la creación / lectura del archivo y simplemente usarlo for /f "tokens=1" %%i in ('find /v "=" heroku_apps.txt ^| find /v ".TXT" ^| findstr /r /v /c:"^$"') do...( ^tenga en cuenta la adición de 's utilizado para escapar de la tubería, para que se pase al forprocesador de comandos y no directamente al procesador de comandos)
user66001

0

Para imprimir todas las líneas en el archivo de texto desde la línea de comando (con expansión retardada):

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

Funciona con espacios en blanco iniciales, líneas en blanco, líneas de espacios en blanco.

Probado en Win 10 CMD


Dios lo intente, pero su primera muestra elimina las ]]]líneas de entrada, la segunda muestra suelta líneas vacías y líneas que comienzan con espacio
jeb

El segundo está destinado a eliminar líneas en blanco. El primero podría modificarse delimssi alguna línea en el archivo de texto comienza con, ]por ejemplo. reemplace con algún personaje que no lo haga, o un personaje de control como retroceso o campana; normalmente no se encuentran en archivos de texto. La razón de delims=]es eliminar los marcadores de posición creadas por /nde findcomando para preservar las líneas en blanco.
Zimba

@jeb: soporte]]] problema solucionado. Ver actualización, para imprimir todas las líneas en el archivo de texto. Funciona en Win 10 CMD también.
Zimba
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.