2008-09-20 21 views
92

Estoy buscando obtener el resultado de un comando como una variable en un script por lotes de Windows (consulte how to get the result of a command in bash para el equivalente de scripts bash). Se prefiere una solución que funcionará en un archivo .bat, pero también se aceptan otras soluciones comunes de script de Windows.¿Cómo obtengo el resultado de un comando en una variable en Windows?

+8

John, es ridículamente difícil encontrar esta ** muy ** pregunta útil. ¿Podría considerar agregar una redacción alternativa como * Cómo ** capturar ** el ** resultado ** de un ** programa ** en una variable en un archivo por lotes de Windows? * –

+3

Google muestra esta página en el 3er lugar. –

+1

Posible duplicado de [Windows asigna asignación de lote de un programa a una variable] (http://stackoverflow.com/questions/2323292/windows-batch-assign-output-of-a-program-to-a-variable) –

Respuesta

24

Si usted tiene que capturar toda la salida del comando se puede utilizar un lote de esta manera: "!"

@ECHO OFF 
IF NOT "%1"=="" GOTO ADDV 
SET VAR= 
FOR /F %%I IN ('DIR *.TXT /B /O:D') DO CALL %0 %%I 
SET VAR 
GOTO END 

:ADDV 
SET VAR=%VAR%!%1 

:END 

Todas las líneas de salida se almacenan en VAR separado con.

@John: ¿hay algún uso práctico para esto? Creo que debería ver PowerShell o cualquier otro lenguaje de programación capaz de realizar tareas de scripts fácilmente (Python, Perl, PHP, Ruby)

+0

La respuesta de una sola línea resolverá el caso específico que tengo. Me di cuenta de que había una opción de varias líneas (o una opción de una sola línea más fácil). Supongo que las capacidades de los archivos bat no son tan buenas. La necesidad es para scripts bat que envuelven aplicaciones Java. Construyendo classpaths principalmente. –

+0

Ten mucho cuidado con eso. GWT también intentó usar archivos de proceso por lotes para iniciar Java con classpaths específicos, que fallaron horriblemente tan pronto como llegó a los directorios con caracteres que no son ASCII (en ese caso era mi casa :)). Ellos desde que reescribieron eso con VBS. – Joey

+17

* ¿hay algún uso práctico para esto? * ¿Estás bromeando? Esto se usa todo el tiempo en otros shells (todos los GNU/Linux, supongo) y es ** muy ** útil. –

-1

Consulte este http://technet.microsoft.com/en-us/library/bb490982.aspx que explica lo que puede hacer con la salida del comando.

+1

Ese artículo solo cubre la redirección y temas relacionados. No responde la pregunta de cómo tomar la salida de un comando y convertirlo en una variable. –

+3

Utilizando su respuesta, se me ocurrió esto: 'git pull> 0 set/P RESULTVAR = <0' editar: Supongo que no sé cómo utilizar los saltos de línea aquí ... cada comando está activado es propia línea. – RibeiroBreno

5

necesita usar el comando SET con el parámetro /P y dirigir su salida hacia él. Por ejemplo, vea http://www.ss64.com/nt/set.html. Trabajará para CMD, no está seguro acerca .bat

Desde un comentario a este post:

Ese enlace tiene el comando "Set /P _MyVar=<MyFilename.txt", que dice que va a establecer _MyVar a la primera línea de MyFilename.txt. Esto podría ser usado como "myCmd > tmp.txt" con "set /P myVar=<tmp.txt". Pero será solamente conseguir la primera línea de la salida, no toda la salida

+1

Ese enlace tiene el comando "Set/P _MyVar = tmp.txt" con "set/P myVar =

+2

mucho mejor que la sintaxis del comando for – JJS

3

Ejemplo para establecer la variable de entorno "V" el archivo más reciente

FOR /F %I IN ('DIR *.* /O:D /B') DO SET V=%I 

en un archivo por lotes que tiene que utilizar el doble prefijo en la variable de bucle:

FOR /F %%I IN ('DIR *.* /O:D /B') DO SET V=%%I 
+2

He visto este enfoque antes, pero parece realmente hacky. También tiene el problema de que solo capturará la última línea de salida del comando en la variable. –

62

el humilde para comando ha acumulado cierta ca interesante capacida- lo largo de los años:

D:\> FOR /F "delims=" %i IN ('date /t') DO set today=%i 
D:\> echo %today% 
Sat 20/09/2008 

Tenga en cuenta que "delims=" sobrescribe el espacio predeterminado y delimitadores de tabulación para que la salida del comando date consigue engullido todos a la vez.

para capturar la salida multi-línea, todavía puede esencialmente ser una de una sola línea (usando la LF variable como el delimitador en la variable resultante):

REM NB:in a batch file, need to use %%i not %i 
setlocal EnableDelayedExpansion 
SET lf=- 
FOR /F "delims=" %%i IN ('dir \ /b') DO if ("!out!"=="") (set out=%%i) else (set out=!out!%lf%%%i) 
ECHO %out% 

para capturar una expresión entubada, utilizar ^|:

FOR /F "delims=" %%i IN ('svn info . ^| findstr "Root:"') DO set "URL=%%i" 
+1

Al igual que con la respuesta de @PabloG, esto solo funcionará para obtener la última línea de salida del comando, "date/t" en este caso. –

+8

Su respuesta me pareció funcionar solo cuando utilicé signos de porcentaje doble, es decir, 'FOR/F" delims = "%% i IN ('date/t') DO establecido hoy = %% i' – Rabarberski

+12

@Rabarberski: Si escribe un comando 'for' directamente en la línea de comando, usa un solo'% '. Si lo usa en un archivo por lotes, usa '%%'. – indiv

20

Para obtener el directorio actual, puede utilizar esto:

CD > tmpFile 
SET /p myvar= < tmpFile 
DEL tmpFile 
echo test: %myvar% 

Sin embargo, está usando un archivo temporal, por lo que no es el más bonito, ¡pero ciertamente funciona! 'CD' coloca el directorio actual en 'tmpFile', 'SET' carga el contenido de tmpFile.

Aquí es una solución para múltiples líneas con "matriz de":

@echo off 

rem --------- 
rem Obtain line numbers from the file 
rem --------- 

rem This is the file that is being read: You can replace this with %1 for dynamic behaviour or replace it with some command like the first example i gave with the 'CD' command. 
set _readfile=test.txt 

for /f "usebackq tokens=2 delims=:" %%a in (`find /c /v "" %_readfile%`) do set _max=%%a 
set /a _max+=1 
set _i=0 
set _filename=temp.dat 

rem --------- 
rem Make the list 
rem --------- 

:makeList 
find /n /v "" %_readfile% >%_filename% 

rem --------- 
rem Read the list 
rem --------- 

:readList 
if %_i%==%_max% goto printList 

rem --------- 
rem Read the lines into the array 
rem --------- 
for /f "usebackq delims=] tokens=2" %%a in (`findstr /r "\[%_i%]" %_filename%`) do set _data%_i%=%%a 
set /a _i+=1 
goto readList 

:printList 
del %_filename% 
set _i=1 
:printMore 
if %_i%==%_max% goto finished 
set _data%_i% 
set /a _i+=1 
goto printMore 

:finished 

pero es posible que desee considerar la posibilidad de trasladarse a otra más potente concha o crear una aplicación para estas cosas. Está ampliando las posibilidades de los archivos por lotes bastante.

+0

¿Hay alguna variación que funcione para capturar varias líneas del comando? –

+4

Para obtener el directorio actual puede usar echo% CD% – Joe

1

Puede capturar todos los resultados en una variable, pero las líneas estarán separadas por un carácter de su elección (# en el ejemplo a continuación) en lugar de un CR-LF real.

@echo off 
setlocal EnableDelayedExpansion 
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i) 
) 
echo directory contains: 
echo %DIR% 

Segunda versión, si necesita imprimir los contenidos línea por línea. Esto se aprovecha del hecho de que no habrá líneas duplicadas de salida desde "dir/b", por lo que puede no funcionar en el caso general.

@echo off 
setlocal EnableDelayedExpansion 
set count=0 
for /f "delims=" %%i in ('dir /b') do (
    if "!DIR!"=="" (set DIR=%%i) else (set DIR=!DIR!#%%i) 
    set /a count = !count! + 1 
) 

echo directory contains: 
echo %DIR% 

for /l %%c in (1,1,%count%) do (
    for /f "delims=#" %%i in ("!DIR!") do (
     echo %%i 
     set DIR=!DIR:%%i=! 
    ) 
) 
2

Si usted está buscando la solución aportada en Using the result of a command as an argument in bash?

entonces aquí es el código:

@echo off 
if not "%1"=="" goto get_basename_pwd 
for /f "delims=X" %%i in ('cd') do call %0 %%i 
for /f "delims=X" %%i in ('dir /o:d /b') do echo %%i>>%filename%.txt 
goto end 

:get_basename_pwd 
set filename=%~n1 

:end 
  • Para ello, será en sí con el resultado del comando CD, misma como pwd.
  • La extracción de cadena en los parámetros devolverá el nombre de archivo/carpeta.
  • obtener el contenido de esta carpeta y añadir a la filename.txt

[Créditos]: Gracias a todas las otras respuestas y algo de investigación en la página Windows XP commands.

2
@echo off 

ver | find "6.1." > nul 
if %ERRORLEVEL% == 0 (
echo Win7 
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a 
%findoutlook% 
) 

ver | find "5.1." > nul 
if %ERRORLEVEL% == 0 (
echo WinXP 
for /f "delims=" %%a in ('DIR "C:\Program Files\Microsoft Office\*Outlook.EXE" /B /P /S') do call set findoutlook=%%a 
%findoutlook% 
) 
echo Outlook dir: %findoutlook% 
"%findoutlook%" 
+0

¡Gracias por publicar una respuesta! Si bien un fragmento de código podría responder a la pregunta, sigue siendo genial agregar información adicional, como explicar, etc. – j0k

2

Simplemente use el resultado del comando FOR. Por ejemplo (dentro de un archivo por lotes):

for /F "delims=" %%I in ('dir /b /a-d /od FILESA*') do (echo %%I) 

Puede utilizar el %%I como el valor que desee. Justo como este: %%I.

¡Y de antemano el %%I no tiene espacios ni caracteres CR y se puede utilizar para las comparaciones!

0

Me gustaría añadir una observación a las soluciones anteriores:

Todas estas sintaxis funcionan perfectamente bien si su mandato se encuentra dentro de la ruta o si el comando es un cmdpath sin espacios ni caracteres especiales.

Pero si intenta utilizar un comando ejecutable ubicado en una carpeta cuya ruta contiene caracteres especiales, deberá encerrar la ruta del comando en comillas dobles (") y luego la sintaxis FOR/F no funcionará.

Ejemplos:

$ for /f "tokens=* USEBACKQ" %f in (
    `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" Hello '"F:\GLW7\Distrib\System\Shells and scripting"'` 
) do echo %f 
The filename, directory name, or volume label syntax is incorrect. 

o

$ for /f "tokens=* USEBACKQ" %f in (
     `"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"` 
) do echo %f 
'F:\GLW7\Distrib\System\Shells' is not recognized as an internal or external command, operable program or batch file. 

o

`$ for /f "tokens=* USEBACKQ" %f in (
    `""F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello World" "F:\GLW7\Distrib\System\Shells and scripting"` 
) do echo %f 
'"F:\GLW7\Distrib\System\Shells and scripting\f2ko.de\folderbrowse.exe"" "Hello' is not recognized as an internal or external command, operable program or batch file. 

En ese caso, la única solución que encontré para usar un comando y almacenar el resultado en una variable es para establecer (temporalmente) el directorio predeterminado al del comando en sí:

pushd "%~d0%~p0" 
FOR /F "tokens=* USEBACKQ" %%F IN (
    `FOLDERBROWSE "Hello world!" "F:\GLW7\Distrib\System\Layouts (print,display...)"` 
) DO (SET MyFolder=%%F) 
popd 
echo My selected folder: %MyFolder% 

El resultado es entonces correcta:

My selected folder: F:\GLW7\Distrib\System\OS install, recovery, VM\ 
Press any key to continue . . . 

Por supuesto que en el ejemplo anterior, supongo que mi archivo por lotes se encuentra en la misma carpeta que el de mi comando ejecutable para que pueda utilizar la sintaxis "% ~ d0% ~ p0". Si este no es tu caso, entonces tienes que encontrar una manera de ubicar tu ruta de comando y cambiar el directorio predeterminado a su ruta.

NB: Para aquellos que se preguntan, el comando de ejemplo utilizado aquí (para seleccionar una carpeta) es FOLDERBROWSE.EXE. Lo encontré en el sitio web f2ko.de (http://f2ko.de/en/cmd.php).

Si alguien tiene una mejor solución para ese tipo de comandos accesibles a través de una ruta compleja, estaré encantado de saber de ella.

Gilles

+0

Puede prefijar su comando con 'CALL'. [FOR/F no funciona si la ruta tiene espacios] (https://stackoverflow.com/a/6478227/463115) – jeb

+0

@jeb: ¡MUCHAS GRACIAS! Ahora mi código <'CALL"% SOURCEDIR% \ FOLDERBROWSE "..." parámetros citados "'> funciona a la perfección. –

Cuestiones relacionadas