valor - ¿Cómo obtengo el resultado de un comando en una variable en Windows?
ver valor variable de entorno cmd (11)
Estoy buscando obtener el resultado de un comando como una variable en un script por lotes de Windows (vea cómo obtener el resultado de un comando en 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.
Consulte este http://technet.microsoft.com/en-us/library/bb490982.aspx que explica qué puede hacer con el resultado del comando.
Ejemplo para establecer en 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, debe usar el prefijo doble en la variable de ciclo:
FOR /F %%I IN (''DIR *.* /O:D /B'') DO SET V=%%I
El comando humilde ha acumulado algunas capacidades interesantes a 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 los delimitadores de pestañas para que la salida del comando de fecha se engulle todo a la vez.
Para capturar salidas de varias líneas, aún puede ser esencialmente un trazador de líneas (usando la variable lf como 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 canalizada, use ^|
:
FOR /F "delims=" %%i IN (''svn info . ^| findstr "Root:"'') DO set "URL=%%i"
Me gustaría agregar una observación a las soluciones anteriores:
Todas estas sintaxis funcionan perfectamente bien SI SU COMANDO SE ENCUENTRA DENTRO DE LA RUTA O SI EL MANDO ES UN CAMINO DE cmD SIN ESPACIOS O 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 su resultado en una variable es establecer (temporalmente) el directorio predeterminado al del comando mismo:
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 correcto:
My selected folder: F:/GLW7/Distrib/System/OS install, recovery, VM/
Press any key to continue . . .
Por supuesto, en el ejemplo anterior, supongo que mi secuencia de comandos por lotes se encuentra en la misma carpeta que la 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.
Nota: Para aquellos que se preguntan, el comando de muestra 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
Para obtener el directorio actual, puede usar 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í hay una solución para líneas múltiples con "array''s":
@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 pasar a otro shell más potente o crear una aplicación para este tipo de cosas. Está ampliando las posibilidades de los archivos por lotes bastante.
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 el contenido 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=!
)
)
Si está buscando la solución provista en Usar el resultado de un comando como argumento en bash?
entonces aquí está 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
- Esto se llamará a sí mismo con el resultado del comando CD, igual que pwd.
- La extracción de cadena en los parámetros devolverá el nombre de archivo / carpeta.
- Obtenga el contenido de esta carpeta y anexe al filename.txt
[Créditos] : gracias a todas las otras respuestas y algunas búsquedas en la página de comandos de Windows XP .
Si tiene que capturar todos los resultados del comando, puede usar un lote como este:
@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 separadas por "!".
@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 scripting fácilmente (Python, Perl, PHP, Ruby)
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 usar el %%I
como el valor que desea. Justo como este: %%I
¡Y de antemano el %%I
no tiene espacios ni caracteres CR y puede usarse para comparaciones!
necesita usar el comando SET
con parameter /P
y dirigir su salida hacia él. Por ejemplo, vea http://www.ss64.com/nt/set.html . Funcionará para CMD, no estoy seguro acerca de los archivos .BAT
De un comentario a esta publicación:
Ese enlace tiene el comando "
Set /P _MyVar=<MyFilename.txt
" que dice que establecerá_MyVar
en la primera línea deMyFilename.txt
. Esto podría usarse como "myCmd > tmp.txt
" con "set /P myVar=<tmp.txt
". Pero solo obtendrá la primera línea de la salida, no toda la salida
@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%"