¿Cómo paso los parámetros de la línea de comando a un archivo por lotes?

Necesito pasar el id y la contraseña a un archivo cmd (o bat) en el momento de ejecutar en lugar de codificarlos en el archivo.

Así es como se ve la línea de comando:

test.cmd admin P@55w0rd > test-log.txt 

Otro consejo útil es usar %* para decir “todo”. Por ejemplo:

 echo off set arg1=%1 set arg2=%2 shift shift fake-command /u %arg1% /p %arg2% %* 

Cuando corres:

 test-command admin password foo bar 

el archivo por lotes anterior se ejecutará:

 fake-command /u admin /p password foo bar 

Puedo tener la syntax ligeramente incorrecta, pero esta es la idea general.

Así es como lo hago.

 @fake-command /u %1 /p %2 

Así es como se ve la línea de comando:

 test.cmd admin P@55w0rd > test-log.txt 

El% 1 se aplica al primer parámetro, el% 2 (y aquí está la parte engañosa) se aplica al segundo. Puede tener hasta 9 parámetros pasados ​​de esta manera.

Si desea manejar de forma inteligente los parámetros que faltan, puede hacer algo como:

 IF %1.==. GOTO No1 IF %2.==. GOTO No2 ... do stuff... GOTO End1 :No1 ECHO No param 1 GOTO End1 :No2 ECHO No param 2 GOTO End1 :End1 

Acceder a los parámetros del lote puede ser simple con% 1,% 2, …% 9 o también% *,
pero solo si el contenido es simple.

No hay una forma sencilla de contenido complejo como "&"^& , ya que no es posible acceder a% 1 sin producir un error.

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

Las líneas se expanden a

 set var="&"& set "var="&"&" set var="&"& set "var="&"&" 

Y cada línea falla, ya que una de las & está fuera de las comillas.

Se puede resolver leyendo de un archivo temporal una versión comentada del parámetro.

 @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 .. %* ).
Así que incluso "&"& podría repetirse sin producir un error, como se comenta.

Pero para poder redirigir la salida del echo on , necesita los dos bucles for.

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 carácter multilínea, incluso después de un rem .

Luego, lee el resultado del parámetro rem del archivo, pero con cuidado.
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 , lo tienes.

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

Sí, y no olvides usar variables como %%1 cuando uses if y for y the gang.

Si olvida el doble % , sustituirá en argumentos de línea de comando (posiblemente nulos) y recibirá algunos mensajes de error bastante confusos.

No hay necesidad de complicarlo. Es simplemente comandos% 1% 2 parámetros, por ejemplo,

 @echo off xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z echo copied %1 to %2 pause 

La “pausa” muestra lo que ha hecho el archivo por lotes y espera a que presione la tecla ANY. Guárdelo como xx.bat en la carpeta de Windows.

Para usarlo, escriba, por ejemplo:

 xx c:\f\30\*.* f:\sites\30 

Este archivo por lotes se ocupa de todos los parámetros necesarios, como copiar solo archivos, que son más nuevos, etc. Lo he usado desde antes de Windows. Si le gusta ver los nombres de los archivos, a medida que se copian, omita el parámetro Q

 @ECHO OFF :Loop IF "%1"=="" GOTO Continue SHIFT GOTO Loop :Continue 

Nota: SI "%1"=="" causará problemas si %1 está entre comillas.

En ese caso, use IF [%1]==[] o, en NT 4 (SP6) y más adelante solamente, IF "%~1"=="" lugar.

Recientemente, un amigo me preguntó sobre este tema, así que pensé en publicar cómo trato los argumentos de línea de comandos en los archivos por lotes.

Esta técnica tiene un poco de sobrecarga, como verá, pero hace que mis archivos por lotes sean muy fáciles de entender y de implementar rápidamente. Además de soportar las siguientes estructuras:

 >template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...] 

La esencia de esto es tener :init ,: :parse , y :main funciones :main .

Ejemplo de uso

 >template.bat /? test v1.23 This is a sample batch file template, providing command-line arguments and flags. USAGE: test.bat [flags] "required argument" "optional argument" /?, --help shows this help /v, --version shows the version /e, --verbose shows detailed output -f, --flag value specifies a named parameter value >template.bat <- throws missing argument error (same as /?, plus..) **** **** **** MISSING "REQUIRED ARGUMENT" **** **** **** >template.bat -v 1.23 >template.bat --version test v1.23 This is a sample batch file template, providing command-line arguments and flags. >template.bat -e arg1 **** DEBUG IS ON UnNamedArgument: "arg1" UnNamedOptionalArg: not provided NamedFlag: not provided >template.bat --flag "my flag" arg1 arg2 UnNamedArgument: "arg1" UnNamedOptionalArg: "arg2" NamedFlag: "my flag" >template.bat --verbose "argument #1" --flag "my flag" second **** DEBUG IS ON UnNamedArgument: "argument #1" UnNamedOptionalArg: "second" NamedFlag: "my flag" 

template.bat

 @::!/dos/rocks @echo off goto :init :header echo %__NAME% v%__VERSION% echo This is a sample batch file template, echo providing command-line arguments and flags. echo. goto :eof :usage echo USAGE: echo %__BAT_NAME% [flags] "required argument" "optional argument" echo. echo. /?, --help shows this help echo. /v, --version shows the version echo. /e, --verbose shows detailed output echo. -f, --flag value specifies a named parameter value goto :eof :version if "%~1"=="full" call :header & goto :eof echo %__VERSION% goto :eof :missing_argument call :header call :usage echo. echo **** **** echo **** MISSING "REQUIRED ARGUMENT" **** echo **** **** echo. goto :eof :init set "__NAME=%~n0" set "__VERSION=1.23" set "__YEAR=2017" set "__BAT_FILE=%~0" set "__BAT_PATH=%~dp0" set "__BAT_NAME=%~nx0" set "OptHelp=" set "OptVersion=" set "OptVerbose=" set "UnNamedArgument=" set "UnNamedOptionalArg=" set "NamedFlag=" :parse if "%~1"=="" goto :validate if /i "%~1"=="/?" call :header & call :usage "%~2" & goto :end if /i "%~1"=="-?" call :header & call :usage "%~2" & goto :end if /i "%~1"=="--help" call :header & call :usage "%~2" & goto :end if /i "%~1"=="/v" call :version & goto :end if /i "%~1"=="-v" call :version & goto :end if /i "%~1"=="--version" call :version full & goto :end if /i "%~1"=="/e" set "OptVerbose=yes" & shift & goto :parse if /i "%~1"=="-e" set "OptVerbose=yes" & shift & goto :parse if /i "%~1"=="--verbose" set "OptVerbose=yes" & shift & goto :parse if /i "%~1"=="--flag" set "NamedFlag=%~2" & shift & shift & goto :parse if not defined UnNamedArgument set "UnNamedArgument=%~1" & shift & goto :parse if not defined UnNamedOptionalArg set "UnNamedOptionalArg=%~1" & shift & goto :parse shift goto :parse :validate if not defined UnNamedArgument call :missing_argument & goto :end :main if defined OptVerbose ( echo **** DEBUG IS ON ) echo UnNamedArgument: "%UnNamedArgument%" if defined UnNamedOptionalArg echo UnNamedOptionalArg: "%UnNamedOptionalArg%" if not defined UnNamedOptionalArg echo UnNamedOptionalArg: not provided if defined NamedFlag echo NamedFlag: "%NamedFlag%" if not defined NamedFlag echo NamedFlag: not provided :end call :cleanup exit /B :cleanup REM The cleanup function is only really necessary if you REM are _not_ using SETLOCAL. set "__NAME=" set "__VERSION=" set "__YEAR=" set "__BAT_FILE=" set "__BAT_PATH=" set "__BAT_NAME=" set "OptHelp=" set "OptVersion=" set "OptVerbose=" set "UnNamedArgument=" set "UnNamedArgument2=" set "NamedFlag=" goto :eof 

Mantengamos esto simple.

Aquí está el archivo .cmd.

 @echo off rem this file is named echo_3params.cmd echo %1 echo %2 echo %3 set v1=%1 set v2=%2 set v3=%3 echo v1 equals %v1% echo v2 equals %v2% echo v3 equals %v3% 

Aquí hay 3 llamadas de la línea de comando.

 C:\Users\joeco>echo_3params 1abc 2 def 3 ghi 1abc 2 def v1 equals 1abc v2 equals 2 v3 equals def C:\Users\joeco>echo_3params 1abc "2 def" "3 ghi" 1abc "2 def" "3 ghi" v1 equals 1abc v2 equals "2 def" v3 equals "3 ghi" C:\Users\joeco>echo_3params 1abc '2 def' "3 ghi" 1abc '2 def' v1 equals 1abc v2 equals '2 v3 equals def' C:\Users\joeco> 
 FOR %%A IN (%*) DO ( REM Now your batch file handles %%A instead of %1 REM No need to use SHIFT anymore. ECHO %%A ) 

Esto hace un bucle sobre los parámetros del lote (% *) ya sea que estén citados o no, luego ecualiza cada parámetro.

Escribí un simple script read_params que se puede llamar como una función (o externo .bat ) y colocará todas las variables en el entorno actual. No modificará los parámetros originales porque la función está siendo call con una copia de los parámetros originales.

Por ejemplo, dado el siguiente comando:

 myscript.bat some -random=43 extra -greeting="hello world" fluff 

myscript.bat podría usar las variables después de llamar a la función:

 call :read_params %* echo %random% echo %greeting% 

Aquí está la función:

 :read_params if not %1/==/ ( if not "%__var%"=="" ( if not "%__var:~0,1%"=="-" ( endlocal goto read_params ) endlocal & set %__var:~1%=%~1 ) else ( setlocal & set __var=%~1 ) shift goto read_params ) exit /B 

Limitaciones

  • No se pueden cargar argumentos sin ningún valor como -force . Podría usar -force=true pero no puedo pensar en una forma de permitir valores en blanco sin conocer una lista de parámetros por adelantado que no tendrá un valor.

Registro de cambios

  • 18/02/2016
    • Ya no requiere una expansión demorada
    • Ahora funciona con otros argumentos de línea de comando buscando - antes de los parámetros.

Para referirse a una variable establecida en la línea de comando, necesitaría usar “% a%”, por ejemplo:

  set a=100 echo %a% output = 100 

Nota: Esto funciona para Windows 7 pro.

Cree un nuevo archivo por lotes (ejemplo: openclass.bat) y escriba esta línea en el archivo:

 java %~n1 

A continuación, coloque el archivo por lotes en, digamos, la carpeta system32, vaya a su archivo de clase Java, haga clic con el botón secundario, Propiedades, Abrir con …, luego encuentre su archivo por lotes, selecciónelo y eso es todo …

Esto funciona para mi.

PD: No puedo encontrar una manera de cerrar la ventana de cmd cuando cierro la clase de Java. Por ahora…

Solución simple (aunque la pregunta es vieja)

Test1.bat

 echo off echo "Batch started" set arg1=%1 echo "arg1 is %arg1%" echo on pause 

CallTest1.bat

 call "C:\Temp\Test1.bat" pass123 

salida

 YourLocalPath>call "C:\Temp\test.bat" pass123 YourLocalPath>echo off "Batch started" "arg1 is pass123" YourLocalPath>pause Press any key to continue . . . 

Donde YourLocalPath es la ruta actual del directorio.

Para mantener las cosas simples, guarde el parámetro param en variable y use la variable para comparar.

No solo es simple de escribir, sino que también es fácil de mantener, por lo que si más tarde otra persona lee el guión después de un largo período de tiempo, será fácil de entender y mantener.

Para escribir código en línea: vea otras respuestas.

Inspirado por una respuesta en otro lugar de @Jon, he creado un algoritmo más general para extraer parámetros nombrados, valores opcionales e interruptores.

Digamos que queremos implementar una utilidad foobar . Requiere un comando inicial. Tiene un parámetro opcional --foo que toma un valor opcional (que no puede ser otro parámetro, por supuesto); si falta el valor, se establece de manera default . También tiene un parámetro opcional --bar que toma un valor requerido . Por último, puede tomar una bandera --baz sin ningún valor permitido. Ah, y estos parámetros pueden venir en cualquier orden.

En otras palabras, se ve así:

 foobar  [--foo []] [--bar ] [--baz] 

Aquí hay una solución:

 @ECHO OFF SETLOCAL REM FooBar parameter demo REM By Garret Wilson SET CMD=%~1 IF "%CMD%" == "" ( GOTO usage ) SET FOO= SET DEFAULT_FOO=default SET BAR= SET BAZ= SHIFT :args SET PARAM=%~1 SET ARG=%~2 IF "%PARAM%" == "--foo" ( SHIFT IF NOT "%ARG%" == "" ( IF NOT "%ARG:~0,2%" == "--" ( SET FOO=%ARG% SHIFT ) ELSE ( SET FOO=%DEFAULT_FOO% ) ) ELSE ( SET FOO=%DEFAULT_FOO% ) ) ELSE IF "%PARAM%" == "--bar" ( SHIFT IF NOT "%ARG%" == "" ( SET BAR=%ARG% SHIFT ) ELSE ( ECHO Missing bar value. 1>&2 ECHO: GOTO usage ) ) ELSE IF "%PARAM%" == "--baz" ( SHIFT SET BAZ=true ) ELSE IF "%PARAM%" == "" ( GOTO endargs ) ELSE ( ECHO Unrecognized option %1. 1>&2 ECHO: GOTO usage ) GOTO args :endargs ECHO Command: %CMD% IF NOT "%FOO%" == "" ( ECHO Foo: %FOO% ) IF NOT "%BAR%" == "" ( ECHO Bar: %BAR% ) IF "%BAZ%" == "true" ( ECHO Baz ) REM TODO do something with FOO, BAR, and/or BAZ GOTO :eof :usage ECHO FooBar ECHO Usage: foobar ^ [--foo [^]] [--bar ^] [--baz] EXIT /B 1 
  • Use SETLOCAL para que las variables no escapen al entorno de llamada.
  • No olvide inicializar las variables SET FOO= , etc. en caso de que alguien los haya definido en el entorno de llamada.
  • Use %~1 para eliminar las comillas.
  • Use IF "%ARG%" == "" y no IF [%ARG%] == [] porque [ y ] no lo ejecute en absoluto con valores que terminen en un espacio.
  • Incluso si SHIFT dentro de un bloque IF , los argumentos actuales como %~1 no se actualizan porque se determinan cuando se analiza el IF . Puedes usar %~1 y %~2 dentro del bloque IF , pero sería confuso porque tienes un SHIFT . Podría poner el SHIFT al final del bloque para mayor claridad, pero podría perderse y / o confundir a las personas también. Así que “capturar” %~1 y %~1 fuera del bloque parece ser lo mejor.
  • No desea utilizar un parámetro en lugar del valor opcional de otro parámetro, por lo que debe verificar IF NOT "%ARG:~0,2%" == "--" .
  • Tenga cuidado solo con SHIFT cuando use uno de los parámetros.
  • El código duplicado SET FOO=%DEFAULT_FOO% es lamentable, pero la alternativa sería agregar un IF "%FOO%" == "" SET FOO=%DEFAULT_FOO% fuera del bloque IF NOT "%ARG%" == "" . Sin embargo, debido a que esto todavía está dentro del bloque IF "%PARAM%" == "--foo" , el valor de %FOO% se habría evaluado y configurado antes de haber ingresado al bloque, por lo que nunca detectaría que tanto el --foo parámetro --foo estaba presente y también que faltaba el valor de %FOO% .
  • Tenga en cuenta que ECHO Missing bar value. 1>&2 ECHO Missing bar value. 1>&2 envía el mensaje de error a stderr.
  • ¿Quieres una línea en blanco en un archivo por lotes de Windows? Tienes que usar ECHO: o una de las variaciones.