Necesito pasar un ID y una contraseña a un archivo por lotes en el momento de la ejecución 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
Necesito pasar un ID y una contraseña a un archivo por lotes en el momento de la ejecución 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
Respuestas:
Otro consejo útil es usar %*
para significar "todos". 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
se ejecutará el archivo por lotes anterior:
fake-command /u admin /p password admin password foo bar
Puede que la sintaxis sea un poco incorrecta, pero esta es la idea general.
shift
"saca" el argumento de la lista. La suposición de OP fue que %*
solo generaría los argumentos restantes, pero no funciona de esa manera, como dijo @Joey.
fake-command /u admin /p password admin password foo bar
. Esto fue señalado por @Joey hace muchos años.
Así es como lo hice:
@fake-command /u %1 /p %2
Así es como se ve el comando:
test.cmd admin P@55w0rd > test-log.txt
El se %1
aplica al primer parámetro que %2
(y aquí está la parte difícil) se aplica al segundo. Puede pasar hasta 9 parámetros de esta manera.
echo %1 %2
y fue rechazada por el caso más simple que no se puede cortar y pegar con a @
y a fake-command
con params, pensando que obtendríamos fake-command.bat
el contenido más tarde (en cuyo caso, el demasiado complicado fake-command.bat
podría tener echo %2 %4
que ignorar los nombres de los parámetros). Mal, tonto. TL; DR: No seas tan tonto como yo. 1. echo echo %1 %2 > test.bat
2 test word1 word2
.. 3. Ganancias.
Si desea manejar de manera 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
El acceso a los parámetros por lotes puede ser simple con% 1,% 2, ...% 9 o también% *,
pero solo si el contenido es simple.
No hay una manera simple para contenidos complejos 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 ellas &
está fuera de las comillas.
Se puede resolver leyendo un archivo temporal una versión remarcada 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% 1 después de una rem
declaración (también funciona con %2 .. %*
).
Entonces, incluso "&"&
podría hacerse eco sin producir un error, como se comenta.
Pero para poder redirigir la salida de echo on
, necesitas los dos bucles for.
Los caracteres adicionales * #
se usan para estar seguros contra contenidos como /?
(mostraría la ayuda para REM
).
O un cursor ^ al final de la línea podría funcionar como un carácter multilínea, incluso después de a rem
.
Luego, lea la salida del parámetro rem del archivo, pero con cuidado.
El FOR / F debería funcionar con la expansión retrasada desactivada, de lo contrario el contenido con "!" Sería destruido.
Después de eliminar los caracteres adicionales param1
, lo tienes.
Y para usar param1
de manera segura, habilite la expansión demorada.
&
, su solución solo funciona con contenido simple
test.bat ^&
y falla. Solo test.bat "&"
funciona, pero ese no era mi punto. No se puede utilizar %*
, %1
de una manera segura y sin la técnica de REM
&
y también comillas"
Sí, y no olvides usar variables como %%1
cuando usas if
y for
y la pandilla.
Si olvida el doble %
, sustituirá los argumentos de la línea de comandos (posiblemente nulos) y recibirá algunos mensajes de error bastante confusos.
if
y for
?
for %%d in (*) do echo %%d
desde la línea de comandos:for %d in (*) do echo %d
@for %%2 in (testing) do @echo %%2 %1
en un archivo por lotes, produce testing 1
cuando se llama con 1 ( test 1
).
%%1
no accede a un argumento de línea de comando, y también es incorrecto para el IF
comando. Solo el FOR
comando (en archivos por lotes) requiere porcentajes dobles, pero incluso así %%1
definiría un parámetro FOR y no accede a los argumentos
No hay necesidad de complicarlo. Es simplemente comando% 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 pulses CUALQUIER tecla. Guarde eso 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 encarga 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, ya que se están copiando, omita el Q
parámetro.
Un amigo me preguntó sobre este tema recientemente, así que pensé en publicar cómo manejo los argumentos de la línea de comandos en archivos por lotes.
Como verás, esta técnica tiene un poco de sobrecarga, pero hace que mis archivos por lotes sean muy fáciles de entender y rápidos de implementar. Además de soportar las siguientes estructuras:
>template.bat [-f] [--flag] [/f] [--namedvalue value] arg1 [arg2][arg3][...]
El jist de que está teniendo los :init
, :parse
y :main
funciones.
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
@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue
Nota: IF "%1"==""
causará problemas si %1
se incluye entre comillas.
En ese caso, use IF [%1]==[]
o, en NT 4 (SP6) y solo más tarde, en su IF "%~1"==""
lugar.
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 desde 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 recorre los parámetros del lote (% *), ya sea que estén entre comillas o no, y luego repite cada parámetro.
test.bat *.txt
, test.bat cat^&dog
oTest.bat /?
Escribí un script simple read_params que se puede llamar como una función (o externa .bat
) y colocará todas las variables en el entorno actual. No modificará los parámetros originales porque la función se está call
editando 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
-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 con anticipación que no tendrá un valor.Registro de cambios
-
parámetros anteriores.En archivo por lotes
set argument1=%1
set argument2=%2
echo %argument1%
echo %argument2%
% 1 y% 2 devuelven los valores de argumento primero y segundo respectivamente.
Y en la línea de comando, pasa el argumento
Directory> batchFileName admin P@55w0rd
La salida será
admin
P@55w0rd
Inspirado por una respuesta en otra parte de @Jon, he creado un algoritmo más general para extraer parámetros con nombre, valores opcionales y conmutadores.
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, el valor predeterminado es default
. También tiene un parámetro opcional --bar
que toma un valor requerido . Por último, puede tomar una bandera --baz
sin valor permitido. Ah, y estos parámetros pueden venir en cualquier orden.
En otras palabras, se ve así:
foobar <command> [--foo [<fooval>]] [--bar <barval>] [--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 ^<command^> [--foo [^<fooval^>]] [--bar ^<barval^>] [--baz]
EXIT /B 1
SETLOCAL
para que las variables no escapen al entorno de llamada.SET FOO=
, etc. en caso de que alguien las haya definido en el entorno de llamada.%~1
para eliminar comillas.IF "%ARG%" == ""
y no IF [%ARG%] == []
porque [
y ]
no juegue tendrá valores que terminen en un espacio.SHIFT
dentro de un IF
bloque, los argumentos actuales como %~1
no se actualizan porque se determinan cuando IF
se analiza. Podrías usar %~1
y %~2
dentro del IF
bloque, pero sería confuso porque tenías un SHIFT
. Puede poner el SHIFT
al final del bloque para mayor claridad, pero eso podría perderse y / o confundir a las personas también. Así que "capturar" %~1
y %~1
fuera del bloque parece lo mejor.IF NOT "%ARG:~0,2%" == "--"
.SHIFT
cuando use uno de los parámetros.SET FOO=%DEFAULT_FOO%
es lamentable, pero la alternativa sería agregar un IF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
fuera del IF NOT "%ARG%" == ""
bloque. Sin embargo, debido a que todavía está dentro del IF "%PARAM%" == "--foo"
bloque, el %FOO%
valor se habría evaluado y establecido antes de ingresar al bloque, por lo que nunca detectaría que tanto el --foo
parámetro estaba presente como que %FOO%
faltaba el valor.ECHO Missing bar value. 1>&2
envía el mensaje de error a stderr.ECHO:
o una de las variaciones.Cree un nuevo archivo por lotes (ejemplo: openclass.bat) y escriba esta línea en el archivo:
java %~n1
Luego coloque el archivo por lotes en, digamos, la carpeta system32, vaya a su archivo de clase Java, haga clic derecho, 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 cmd cuando cierro la clase Java. Por ahora...
start /wait java %~n1
Solución simple (aunque la pregunta es antigua)
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 comando param en variable y use 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 alguna otra persona o usted lee su 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.
Para usar el bucle, obtenga todos los argumentos y en lote puro:
Obs: Para usar sin:?*&<>
@echo off && setlocal EnableDelayedExpansion
for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && (
call set "_arg_[!_cnt!]=!_arg_!" && for /l %%l in (!_cnt! 1 !_cnt!
)do echo/ The argument n:%%l is: !_arg_[%%l]!
)
goto :eof
Su código está listo para hacer algo con el número de argumento donde lo necesita, como ...
@echo off && setlocal EnableDelayedExpansion
for %%Z in (%*)do set "_arg_=%%Z" && set/a "_cnt+=1+0" && call set "_arg_[!_cnt!]=!_arg_!"
)
fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
?*&<>