start for finish batch array batch-file iteration cmd

batch-file - array - batch wait for command to finish



¿Cómo funciona "FOR" en el archivo por lotes cmd? (12)

He estado programando en docenas de idiomas durante 20 años, pero nunca pude entender cómo funciona "FOR" en el archivo por lotes del shell de Windows CMD, sin importar cuánto lo intenté. Yo leo

http://www.amazon.com/Windows-Administration-Command-Line-Vista/dp/0470046163/ref=sr_1_1?ie=UTF8&s=books&qid=1241362727&sr=8-1

http://www.ss64.com/nt/for.html

y varios otros artículos en Internet, pero aún confunden y no pueden lograr nada.

¿Puede alguien darme una explicación concisa de cómo funciona "FOR" en general?

Para una pregunta un poco más específica, ¿cómo puedo iterar a través de cada ruta en la variable% PATH%? Lo he intentado con

rem showpathenv.bat for /f "delims=;" %%g in ("%PATH%") do echo %%g

Eso mostraría solo el primer camino, no todos. Por qué ? Qué hice mal ?



Esto funciona para mí:

@ECHO OFF SETLOCAL ENABLEDELAYEDEXPANSION ENABLEEXTENSIONS @REM insure path is terminated with a ; set tpath=%path%; echo. :again @REM This FOR statement grabs the first element in the path FOR /F "delims=;" %%I IN ("%TPATH%") DO ( echo %%I @REM remove the current element of the path set TPATH=!TPATH:%%I;=! ) @REM loop back if there is more to do. IF DEFINED TPATH GOTO :again ENDLOCAL


Funciona para mí, pruébalo.

para / f "tokens = * delims =;" % g in (''echo% PATH%'') do echo% g%


Funciona para mí, pruébalo.

for /f "delims=;" %g in (''echo %PATH%'') do echo %g%


La idea de Mark fue buena, pero tal vez olvidó que algunos caminos tienen espacios en ellos. Reemplazando '';'' con '''' '''' ''en su lugar cortaría todas las rutas en cadenas entrecomilladas.

set _path="%PATH:;=" "%" for %%p in (%_path%) do if not "%%~p"=="" echo %%~p

Así que aquí, tienes tus caminos mostrados.

El comando FOR en cmd tiene una curva de aprendizaje tediosa, especialmente porque las variables reaccionan dentro de las declaraciones () ... puedes asignar cualquier variable, pero no puedes leerla dentro de (), a menos que uses la " setlocal ENABLEDELAYEDEXPANSION ", y por lo tanto también usa las variables con !! ''s en lugar de %%'' s (! _var!)

Actualmente, sigo exclusivamente script con cmd, para el trabajo, tuve que aprender todo esto :)


Ninguna de las respuestas realmente funciona. He logrado encontrar la solución yo mismo. Esto es un poco hackish, pero me solucionó el problema:

echo off setlocal enableextensions setlocal enabledelayedexpansion set MAX_TRIES=100 set P=%PATH% for /L %%a in (1, 1, %MAX_TRIES%) do ( for /F "delims=;" %%g in ("!P!") do ( echo %%g set P=!P:%%g;=! if "!P!" == "%%g" goto :eof ) )

Oh ! ¡Odio la programación de archivos por lotes!

Actualizado

La solución de Mark es más simple, pero no funcionará con path que contenga espacios en blanco. Esta es una versión poco modificada de la solución de Mark

echo off setlocal enabledelayedexpansion set NonBlankPath=%PATH: =#% set TabbedPath=%NonBlankPath:;= % for %%g in (%TabbedPath%) do ( set GG=%%g echo !GG:#= ! )


No pude resistirme a tirar esto por viejo, como este hilo es ... Generalmente, cuando surge la necesidad de iterar a través de cada uno de los archivos en PATH, todo lo que realmente desea hacer es encontrar un archivo en particular ... Si ese es el caso , este one-liner escupirá el primer directorio en el que encuentre tu archivo:

(ejemplo: buscando java.exe)

for %%x in (java.exe) do echo %%~dp$PATH:x


Sé que esto es SUPER viejo ... pero solo por diversión, decidí intentarlo:

@Echo OFF setlocal set testpath=%path: =#% FOR /F "tokens=* delims=;" %%P in ("%testpath%") do call :loop %%P :loop if ''%1''=='''' goto endloop set testpath=%1 set testpath=%testpath:#= % echo %testpath% SHIFT goto :loop :endloop pause endlocal exit

Esto no requiere un conteo e irá hasta que termine. Tuve el mismo problema con los espacios, pero pasó a través de toda la variable. La clave para esto es las etiquetas de bucle y la función SHIFT .


También debe usar los tokens=1,2,... parte de las opciones que permite el ciclo for . Esto aquí hará lo que posiblemente quieras:

for /f "tokens=1,2,3,4,5,6,7,8,9,10,11,12 delims=;" %a in ("%PATH%") ^ do ( ^ echo. %b ^ & echo. %a ^ & echo. %c ^ & echo. %d ^ & echo. %e ^ & echo. %f ^ & echo. %g ^ & echo. %h ^ & echo. %i ^ & echo. %j ^ & echo. %k ^ & echo. ^ & echo. ...and now for some more... ^ & echo. ^ & echo. %a ^| %b ___ %c ... %d ^ & dir "%e" ^ & cd "%f" ^ & dir /tw "%g" ^ & echo. "%h %i %j %k" ^ & cacls "%f")

Este ejemplo procesa los primeros 12 tokens (= directorios de% path%) solamente. Utiliza una enumeración explícita de cada uno de los tokens usados. Tenga en cuenta que los nombres de los tokens distinguen entre mayúsculas y minúsculas:% a es diferente de% A.

Para guardar las rutas con espacios, rodee todo % x con comillas como esta "% i". No lo hice aquí, donde solo hago eco de los tokens.

También podría hacer s.th. Me gusta esto:

for /f "tokens=1,3,5,7-26* delims=;" %a in ("%PATH%") ^ do ( ^ echo. %c ^ & echo. %b ^ & echo. %a ^ & echo. %d ^ & echo. %e ^ & echo. %f ^ & echo. %g ^ & echo. %h ^ & echo. %i ^ & echo. %j ^ & echo. %k )

Éste omite tokens 2,4,6 y usa un pequeño atajo (" 7-26 ") para nombrar al resto de ellos. Observe cómo% c,% b,% a se procesan en orden inverso esta vez, y cómo ahora "significan" tokens diferentes, en comparación con el primer ejemplo.

Entonces esta seguramente no es la explicación concisa que pediste. Pero tal vez los ejemplos ayudan a aclarar un poco mejor ahora ...


Tiene la idea correcta, pero for /f está diseñada para trabajar en archivos o comandos de varias líneas, no en cadenas individuales.

En su forma más simple, for es como Perl''s, o el foreach todos los demás idiomas. Le pasa una lista de tokens y los itera, llamando al mismo comando cada vez.

for %a in (hello world) do @echo %a

Las extensiones simplemente proporcionan formas automáticas de compilar la lista de tokens. La razón por la que su código actual no genera nada es eso '' ; ''es el símbolo predeterminado de fin de línea (comentario). Pero incluso si cambia eso, tendría que usar %%g, %%h, %%i, ... para acceder a los tokens individuales, lo que limitará severamente su archivo por lotes.

Lo más cerca que puede llegar a lo que pide es:

set TabbedPath=%PATH:;= % for %%g in (%TabbedPath%) do echo %%g

Pero eso fallará en las rutas citadas que contienen puntos y comas.

En mi experiencia, for /l for /r son buenos para extender los comandos existentes, pero de lo contrario es extremadamente limitado. Puede hacer que sea ligeramente más potente (y confuso) con la expansión de la variable retrasada ( cmd /v:on ), pero en realidad solo sirve para listas de nombres de archivos.

Sugiero usar WSH o PowerShell si necesita realizar manipulación de cadenas. Si está intentando escribir whereis para Windows, intente where /? .


FOR esencialmente itera sobre las "líneas" en el conjunto de datos. En este caso, hay una línea que contiene la ruta. El "delims=;" simplemente le está diciendo que se separe en punto y coma. Si cambia el cuerpo para que haga un echo %%g,%%h,%%i,%%j,%%k , verá que está tratando la entrada como una sola línea y dividiéndola en múltiples tokens.


for /f itera por entrada de línea, por lo que en tu programa solo se generará la primera ruta.

su programa trata% PATH% como entrada de una línea, y delimita por ; , coloque el primer resultado en %% g, luego genere %% g (primer camino delimitado).