Obtener la lista de argumentos pasados en Windows batch script (.bate)


Me gustaría encontrar una contraparte por lotes de Windows para el $@ de Bash que contenga una lista de todos los argumentos pasados a un script.

O tengo que molestarme con shift?

Author: RBerteig, 2008-12-10

13 answers

Dancavallaro lo tiene correcto, %* para todos los parámetros de la línea de comandos (excluyendo el nombre del script en sí). También puede encontrar estos útiles:

%0 - el comando utilizado para llamar al archivo por lotes (podría ser foo, ..\foo, c:\bats\foo.bat, etc.)
%1 es el primer parámetro de línea de comandos,
%2 es el segundo parámetro de línea de comandos,
y así sucesivamente hasta %9 (y SHIFT se puede usar para aquellos después del 9).

%~nx0 - el nombre real del archivo por lotes, independientemente de método de llamada (some-batch.mtd)
%~dp0 - unidad y ruta al script (d:\scripts)
%~dpnx0 - es el nombre completo de la ruta de acceso del script (d:\scripts\some-batch.mtd)

Más info ejemplos en http://www.ss64.com/nt/syntax-args.html y http://www.robvanderwoude.com/parameters.html

 507
Author: matt wilkie,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-06-10 07:19:48

%* parece contener todos los argumentos pasados al script.

 111
Author: dancavallaro,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-10 19:44:28

%1 ... %n y %* contiene los argumentos, pero puede ser complicado acceder a ellos, porque el contenido será interpretado.
Por lo tanto, es imposible manejar algo como esto con declaraciones normales

myBatch.bat "&"^&

Cada línea falla, como cmd.exe intenta ejecutar uno de los ampersands (el contenido de %1 es "&"&)

set var=%1
set "var=%1"
set var=%~1
set "var=%~1"

Pero existe una solución alternativa con un archivo temporal

@echo off
SETLOCAL DisableDelayedExpansion

SETLOCAL
for %%a in (1) do (
    set "prompt=$_"
    echo on
    for %%b in (1) do rem * #%1#
    @echo off
) > param.txt
ENDLOCAL

for /F "delims=" %%L in (param.txt) do (
  set "param1=%%L"
)
SETLOCAL EnableDelayedExpansion
set "param1=!param1:*#=!"
set "param1=!param1:~0,-2!"
echo %%1 is '!param1!'

El truco es habilitar echo on y expandir el %1 después de un rem sentencia (funciona también con %2 .. %*).
Pero para poder redirigir la salida de echo on, necesita los dos BUCLES FOR.

Los caracteres adicionales * # se utilizan para ser seguros contra contenidos como /? (mostraría la ayuda para REM).
O un caret ^ al final de la línea podría funcionar como un carácter multilínea.

El FOR / F debería funcionar con la expansión diferida desactivada, de lo contrario contents con"!"sería destruido.
Después de eliminar los caracteres adicionales en param1 y lo tienes.

Y para usar param1 de manera segura, habilite la expansión retardada.

Editar: Una observación a %0

%0 contiene el comando utilizado para llamar al lote, también preservando el caso como en FoO.BaT
Pero después de una llamada a una función %0 y también en %~0 contiene el nombre de la función (o mejor la cadena que se utilizó para llamar a la función).
Pero con %~f0 todavía puede recordar el nombre del archivo.

@echo off
echo main %0, %~0, %~f0
call :myLabel+xyz
exit /b

:MYlabel
echo func %0, %~0, %~f0
exit /b

Salida

main test.bat, test.bat, C:\temp\test.bat
func :myLabel+xyz, :myLabel+xyz, C:\temp\test.bat
 56
Author: jeb,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-07 07:35:38

Lo encontré la próxima vez cuando necesite buscar esta información. En lugar de abrir un navegador y buscarlo en Google, simplemente puedes escribir call /? en tu cmd y lo obtendrás:

...

%* in a batch script refers to all the arguments (e.g. %1 %2 %3
    %4 %5 ...)

Substitution of batch parameters (%n) has been enhanced.  You can
now use the following optional syntax:

    %~1         - expands %1 removing any surrounding quotes (")
    %~f1        - expands %1 to a fully qualified path name
    %~d1        - expands %1 to a drive letter only
    %~p1        - expands %1 to a path only
    %~n1        - expands %1 to a file name only
    %~x1        - expands %1 to a file extension only
    %~s1        - expanded path contains short names only
    %~a1        - expands %1 to file attributes
    %~t1        - expands %1 to date/time of file
    %~z1        - expands %1 to size of file
    %~$PATH:1   - searches the directories listed in the PATH
                   environment variable and expands %1 to the fully
                   qualified name of the first one found.  If the
                   environment variable name is not defined or the
                   file is not found by the search, then this
                   modifier expands to the empty string

The modifiers can be combined to get compound results:

    %~dp1       - expands %1 to a drive letter and path only
    %~nx1       - expands %1 to a file name and extension only
    %~dp$PATH:1 - searches the directories listed in the PATH
                   environment variable for %1 and expands to the
                   drive letter and path of the first one found.
    %~ftza1     - expands %1 to a DIR like output line

In the above examples %1 and PATH can be replaced by other
valid values.  The %~ syntax is terminated by a valid argument
number.  The %~ modifiers may not be used with %*
 36
Author: KFL,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-05-17 13:42:45

La forma de recuperar todos los argumentos de un script es aquí:

@ECHO off
ECHO The %~nx0 script args are...
for %%I IN (%*) DO ECHO %%I
pause
 19
Author: djangofan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-04 15:36:45

Aquí hay una manera bastante simple de obtener los args y establecerlos como env vars. En este ejemplo solo me referiré a ellos como Claves y valores.

Guarde el siguiente ejemplo de código como "args.bate". A continuación, llame al archivo por lotes guardado desde una línea de comandos. ejemplo: arg.bat x x 90 {y 120

He proporcionado algunos comandos de eco para guiarte a través del proceso. Pero el el resultado final es que --x tendrá un valor de 90 y --y tendrá un valor de 120(es decir, si ejecuta el ejemplo como se especifica arriba ;-) ).

Luego puede usar la instrucción condicional 'if defined' para determinar si debe ejecutar o no su bloque de código. Así que digamos que corre: "arg.bat hello x hola-mundo" Entonces podría usar la sentencia "IF DEFINED echo x echo %x x%" y los resultados serían "hello-world". Debería tener más sentido si ejecuta el lote.

@setlocal enableextensions enabledelayedexpansion
@ECHO off
ECHO.
ECHO :::::::::::::::::::::::::: arg.bat example :::::::::::::::::::::::::::::::
ECHO :: By:      User2631477, 2013-07-29                                   ::
ECHO :: Version: 1.0                                                         ::
ECHO :: Purpose: Checks the args passed to the batch.                        ::
ECHO ::                                                                      ::
ECHO :: Start by gathering all the args with the %%* in a for loop.          ::
ECHO ::                                                                      ::
ECHO :: Now we use a 'for' loop to search for our keys which are identified  ::
ECHO :: by the text '--'. The function then sets the --arg ^= to the next    ::
ECHO :: arg. "CALL:Function_GetValue" ^<search for --^> ^<each arg^>         ::
ECHO ::                                                                      ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::

ECHO.

ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: From the command line you could pass... arg.bat --x 90 --y 220       ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO.Checking Args:"%*"

FOR %%a IN (%*) do (
    CALL:Function_GetValue "--","%%a" 
)

ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: Now lets check which args were set to variables...                   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO :: For this we are using the CALL:Function_Show_Defined "--x,--y,--z"   ::
ECHO ::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
CALL:Function_Show_Defined "--x,--y,--z"
endlocal
goto done

:Function_GetValue

REM First we use find string to locate and search for the text.
echo.%~2 | findstr /C:"%~1" 1>nul

REM Next we check the errorlevel return to see if it contains a key or a value
REM and set the appropriate action.

if not errorlevel 1 (
  SET KEY=%~2
) ELSE (
  SET VALUE=%~2
)
IF DEFINED VALUE (
    SET %KEY%=%~2
    ECHO.
    ECHO ::::::::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::
    ECHO :: The KEY:'%KEY%' is now set to the VALUE:'%VALUE%'                     ::
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
    ECHO %KEY%=%~2
    ECHO.
    REM It's important to clear the definitions for the key and value in order to
    REM search for the next key value set.
    SET KEY=
    SET VALUE=
)
GOTO:EOF

:Function_Show_Defined 
ECHO.
ECHO ::::::::::::::::::: %~0 ::::::::::::::::::::::::::::::::
ECHO :: Checks which args were defined i.e. %~2
ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
ECHO.
SET ARGS=%~1
for %%s in (%ARGS%) DO (
    ECHO.
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO :: For the ARG: '%%s'                         
    IF DEFINED %%s (
        ECHO :: Defined as: '%%s=!%%s!'                                             
    ) else (
        ECHO :: Not Defined '%%s' and thus has no value.
    )
    ECHO :::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::::
    ECHO.
)
goto:EOF

:done
 3
Author: user2631477,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-04-17 20:34:02

El siguiente código simula una matriz ('params') - toma los parámetros recibidos por el script y los almacena en las variables params_1.. params_n, donde n=params_0=el número de elementos de la matriz:

@echo off

rem Storing the program parameters into the array 'params':
rem Delayed expansion is left disabled in order not to interpret "!" in program parameters' values;
rem however, if a parameter is not quoted, special characters in it (like "^", "&", "|") get interpreted at program launch
set /a count=0
:repeat
    set /a count+=1
    set "params_%count%=%~1"
    shift
    if defined params_%count% (
        goto :repeat
    ) else (
        set /a count-=1
    )    
set /a params_0=count

rem Printing the program parameters stored in the array 'params':
rem After the variables params_1 .. params_n are set with the program parameters' values, delayed expansion can
rem be enabled and "!" are not interpreted in the variables params_1 .. params_n values
setlocal enabledelayedexpansion
    for /l %%i in (1,1,!params_0!) do (
        echo params_%%i: "!params_%%i!"
    )
endlocal

pause
goto :eof
 2
Author: ,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-01-21 13:41:15
@echo off
:start

:: Insert your code here
echo.%%1 is now:%~1
:: End insert your code here

if "%~2" NEQ "" (
    shift
    goto :start
)
 0
Author: user298107,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-12 12:49:25

Mucha de la información anterior me llevó a investigar más y, en última instancia, mi respuesta, así que quise contribuir con lo que terminé haciendo con la esperanza de que ayude a otra persona:

  • También quería pasar un número variado de variables a un archivo por lotes para que pudieran ser procesados dentro del archivo.

  • Estaba de acuerdo con pasarlos al archivo por lotes usando comillas

  • Me gustaría que se procesaran de manera similar a la siguiente, pero usando un bucle en lugar de escribir salida manual:

, Así que quería ejecutar esto:

prog_ZipDeleteFiles.bat "_appPath=C:\Services\Logs\PCAP" "_appFile=PCAP*.?"

Y a través de la magia de los bucles for haga esto dentro del archivo por lotes:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

El problema que estaba teniendo es que todos mis intentos de usar un bucle for no estaban funcionando. El siguiente ejemplo:

for /f "tokens* delims= " in %%A (%*) DO (
   set %%A
)

Simplemente haría:

set "_appPath=C:\Services\Logs\PCAP"

Y no:

set "_appPath=C:\Services\Logs\PCAP"
set "_appFile=PCAP*.?"

Incluso después de configurar

SETLOCAL EnableDelayedExpansion

La razón fue que el bucle for leyó toda la línea y asignó mi segundo parámetro a %%B durante la primera iteración de bucle. Debido a que % * representa todos los argumentos, solo hay una sola línea para procesar-ergo solo ocurre una pasada del bucle for. Esto es por diseño resulta, y mi lógica estaba equivocada.

Así que dejé de intentar usar un bucle for y simplifiqué lo que estaba tratando de hacer usando if, shift y una sentencia goto. De acuerdo es un poco de un truco, pero es más adecuado para mis necesidades. Puedo recorrer todos los argumentos y luego usar una sentencia if para abandonar el bucle una vez que los procese todo.

La declaración ganadora por lo que estaba tratando de lograr:

echo on
:processArguments
:: Process all arguments in the order received
if defined %1 then (
    set %1
    shift
    goto:processArguments
) ELSE (
    echo off 
)

ACTUALIZACIÓN-Tuve que modificar a lo siguiente en su lugar, estaba exponiendo todas las variables de entorno al intentar hacer referencia a %1 y usar shift de esta manera:

echo on
shift
:processArguments
:: Process all arguments in the order received
if defined %0 then (
    set %0
    shift
    goto:processArguments
) ELSE (
    echo off 
)
 0
Author: John Ahearn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-03-30 22:04:32

Si tiene parámetros entre comillas que contienen espacios, %* no funcionará correctamente. La mejor solución que he encontrado es tener un bucle que une todos los argumentos: https://serverfault.com/a/22541

set args=%1
shift
:start
if [%1] == [] goto done
set args=%args% %1
shift
goto start

:done
(use %args% here)
 0
Author: Speedstone,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-08-17 13:36:21

Versión de Windows (aunque necesita socat)

C:\Program Files (x86)\Git\bin>type gitproxy.cmd
socat STDIO PROXY:proxy.mycompany.de:%1:%2,proxyport=3128

Configurándolo:

C:\Users\exhau\AppData\Roaming\npm>git config --global core.gitproxy gitproxy.cmd
 -1
Author: Jabo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-26 07:55:56

Puede usar %1, %2 etc para acceder a los argumentos de la línea de comandos. No creo que haya una variable que contenga toda la lista. Es posible que pueda escribir un bucle simple que determine cuántos argumentos se pasaron.

EDITAR: Aparentemente hay:)

 -2
Author: codelogic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-12-10 19:44:08

Para alguien que necesita barra invertida al final de basepath

set source=%~dp0
::Remove the trailing backslash from source
IF %source:~-1%==\ SET source=%source:~0,-1%
echo %source%
 -4
Author: Deniz Porsuk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-12 13:40:15