Obtenga la lista de argumentos pasados ​​en el script por lotes de Windows (.bat)

Me gustaría encontrar una contraparte del lote de Windows para $@ Bash que contenga una lista de todos los argumentos pasados ​​a un script.

¿O tengo que molestarme con shift ?

dancavallaro tiene razón, %* para todos los parámetros de 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 comando,
%2 es el segundo parámetro de línea de comando,
y así hasta %9 (y SHIFT se puede usar para aquellos después del 9no).

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

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

%* parece contener todos los argumentos pasados ​​al script.

%1%n y %* contiene los argumentos, pero puede ser difícil 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, ya que cmd.exe intenta ejecutar uno de los signos y signos (el contenido de% 1 es "&"& )

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

Pero existe una solución 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 una instrucción rem (también funciona con% 2 ..% *).
Pero para poder redirigir la salida del echo on , necesitas los dos FOR-LOOPS.

Los caracteres adicionales * # se usan para protegerse contra contenidos como /? (mostraría la ayuda para REM).
O una referencia en el extremo de la línea podría funcionar como un personaje de línea múltiple.

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

Y para usar param1 de forma segura, habilite la expansión retrasada.

Editar: Una observación a% 0

%0 contiene el comando usado 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 recuperar 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 

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

 ... %* in a batch script refers to all the arguments (eg %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 %* 

La forma de recuperar todos los argumentos a un script está aquí:

 @ECHO off ECHO The %~nx0 script args are... for %%I IN (%*) DO ECHO %%I pause 

Aquí hay una forma bastante simple de obtener los argumentos y establecerlos como variables. En este ejemplo, me referiré a ellos como Llaves y valores.

Guarde el siguiente ejemplo de código como “args.bat”. Luego llame al archivo por lotes que guardó desde una línea de comando. ejemplo: arg.bat –x 90 –y 120

He proporcionado algunos comandos de eco para guiarte en el proceso. Pero 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 ‘si está definida’ para determinar si ejecutará o no su bloque de código. Así que digamos run: “arg.bat –x hello-world” Podría usar la frase “IF DEFINED –x echo% – 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" ^ ^ :: 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 ie %~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 

El siguiente código simula una matriz (‘ params ‘): toma los parámetros recibidos por la secuencia de comandos y los almacena en las variables params_1 .. params_n , donde n = params_0 = la cantidad 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 
 @echo off
 :comienzo

 :: Inserta tu código aquí
 echo. %% 1 ahora es:% ~ 1
 :: End inserta tu código aquí

 si "% ~ 2" NEQ "" (
     cambio
     Ir a: inicio
 ) 

Mucha de la información anterior me llevó a una mayor investigación y finalmente a mi respuesta, así que quería contribuir con lo que terminé haciendo con la esperanza de que ayude a alguien más:

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

  • Estaba bien con pasarlos al archivo por lotes usando comillas

  • Me gustaría que se procesaran de manera similar al siguiente, pero usando un bucle en lugar de escribir de forma 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 for bucles hacer esto dentro del archivo por lotes:

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

El problema que estaba teniendo es que todos mis bashs de usar un bucle for no funcionaban. 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 la configuración

 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 del ciclo. Debido a que% * representa todos los argumentos, solo hay una línea que procesar, por ejemplo, solo ocurre una pasada del ciclo 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 statement goto. Está de acuerdo que es un truco, pero se adapta mejor a mis necesidades. Puedo recorrer todos los argumentos y luego usar una instrucción if para abandonar el ciclo una vez que los proceso a todos.

La statement ganadora de 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 continuación en lugar de eso, 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 ) 

Si tiene parámetros entre comillas que contienen espacios, %* no funcionará correctamente. La mejor solución que encontré 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) 

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 

Puede usar %1, %2 etc. para acceder a los argumentos de línea de comando. 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 🙂

Para alguien que necesita una barra diagonal inversa desde el sendero base

 set source=%~dp0 ::Remove the trailing backslash from source IF %source:~-1%==\ SET source=%source:~0,-1% echo %source%