¿Cómo puedo pasar argumentos a un archivo por lotes?

1167

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
Keng
fuente
8
Para "todo lo demás", vea el comentario de Greg Hegill sobre cómo obtener los parámetros del archivo por lotes desde la enésima posición.
Matt Wilkie
Tengo un script de inicio de entorno que empujará mi nombre de usuario / contraseña a las variables de entorno ... para que no tenga que escribirlas cada vez ... Sin embargo, uso bash la mayor parte del tiempo (linux, mac y Windows), y necesita usarlo para configuraciones de proxy en scripts, etc. para el trabajo.
Rastreador1

Respuestas:

1032

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.

Greg Hewgill
fuente
123
% * en realidad se expande a todos los parámetros independientemente del cambio. Entonces, incluso después de los dos turnos, todavía tendría los dos primeros argumentos en% *. Puede usar algo como esto: stackoverflow.com/questions/761615/… para obtener una variable que contenga todo menos los primeros n parámetros.
Joey
1
¡Tenga en cuenta que% * no funciona en todas partes! Por ejemplo, no funciona con DOSBox 0.73 (tal vez este es un error que debería informarse).
Denilson Sá Maia
28
No es un error porque% * nunca funcionó en MS-DOS o Win9x en primer lugar.
Kef Schecter el
Creo que 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.
NathanAldenSr
55
Esta respuesta es incorrecta. En realidad resulta en fake-command /u admin /p password admin password foo bar. Esto fue señalado por @Joey hace muchos años.
jwdonahue
286

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 %1aplica 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.

Keng
fuente
16
Si eres tan tonto como yo, tu mente estaba buscando echo %1 %2y fue rechazada por el caso más simple que no se puede cortar y pegar con a @y a fake-commandcon params, pensando que obtendríamos fake-command.batel contenido más tarde (en cuyo caso, el demasiado complicado fake-command.batpodría tener echo %2 %4que ignorar los nombres de los parámetros). Mal, tonto. TL; DR: No seas tan tonto como yo. 1. echo echo %1 %2 > test.bat2 test word1 word2.. 3. Ganancias.
ruffin
143

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
thelsdj
fuente
2
¿Cuál es el significado de punto / período en estas operaciones de igualdad?
Chris
44
Básicamente, si% 1 está vacío, esto terminará siendo IF. ==. y entonces el GOTO sucederá. Usamos x aquí entonces: SI x% 1 == x -> SI x == x -> verdadero
Carl
1
¿Debería preguntar cuál es el valor de un "argumento no proporcionado"? ¿De nuevo lo que debe comprobar un "argumento no proporcionado"? Luego, si no tiene una respuesta, debe usar un truco como el de los puntos. Recuerde que, como se indica aquí ss64.com/nt/if.html "De hecho, puede usar casi cualquier carácter para esto un '~' o llaves, {} o incluso el número 4, pero los corchetes tienden a elegirse porque no tienen ningún significado especial ".
Adriano GV Esposito
89

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 ony expandir% 1 después de una remdeclaració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 param1de manera segura, habilite la expansión demorada.

jeb
fuente
para / F "tokens = *" %% a in ('echo% *') establece "all_args = %% a"
Kevin Edwards
@KevinEdwards Entonces pruébelo con uno &, su solución solo funciona con contenido simple
jeb
@KevinEdwards Lo probé test.bat ^&y falla. Solo test.bat "&"funciona, pero ese no era mi punto. No se puede utilizar %*, %1de una manera segura y sin la técnica de REM
Jeb
Ah, sí, un descuido no se escapa correctamente. Necesita cotizaciones, lo cual es factible para todos los casos de uso que he encontrado. Solo quería pasarlo. Gracias por probarlo! Saludos :)
Kevin Edwards
2
@jwdonahue Sí, es complicado (pero no demasiado complicado). Pero especialmente para las contraseñas podría ser necesario, al menos algunas de mis contraseñas contienen símbolos &y también comillas"
jeb
59

Sí, y no olvides usar variables como %%1cuando usas ify fory 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.

Frank Krueger
fuente
%% es solo para ify for?
Royi Namir
25
Es peor que eso: %% se usa para prefijar variables y parámetros de línea de comandos dentro de archivos por lotes. Pero cuando usa estos comandos desde la línea de comandos, solo usa% para prefijar. Ejemplo: dentro del lote: for %%d in (*) do echo %%ddesde la línea de comandos:for %d in (*) do echo %d
Steve Midgley
11
@SteveMidgley Voté tu comentario probablemente hace aproximadamente un año. Luego lo olvidé rápidamente y justo hoy estaba intentando y mirando confusamente mi bucle for en la línea de comando y preguntándome por qué se tiró un pedo y no hizo nada más. Así que aquí hay otro voto virtual de mi parte. Volveré en otro año más o menos cuando vuelva a encontrar el mismo problema.
icc97
Por lo general, reservamos los dígitos para el procesamiento de la línea de comandos y el doble por ciento solo se aplica a la declaración for, que yo sepa. @for %%2 in (testing) do @echo %%2 %1en un archivo por lotes, produce testing 1cuando se llama con 1 ( test 1).
jwdonahue
2
La respuesta es incorrecta. %%1no accede a un argumento de línea de comando, y también es incorrecto para el IFcomando. Solo el FORcomando (en archivos por lotes) requiere porcentajes dobles, pero incluso así %%1definiría un parámetro FOR y no accede a los argumentos
jeb
51

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 Qparámetro.

DearWebby
fuente
41

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, :parsey :mainfunciones.

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
wasatchwizard
fuente
32
@ECHO OFF
:Loop
IF "%1"=="" GOTO Continue
SHIFT
GOTO Loop
:Continue

Nota: IF "%1"==""causará problemas si %1se incluye entre comillas.

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

hora correcta
fuente
Es cierto, pero apenas toca el tema.
jwdonahue
22

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>
Amor y paz - Joe Codeswell
fuente
20
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.

Amr Ali
fuente
Pero falla con muchos argumentos diferentes, como test.bat *.txt, test.bat cat^&dogoTest.bat /?
jeb
19

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á calleditando 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 valor como -force. Podría usar, -force=truepero 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

  • 18/02/2016
    • Ya no requiere expansión demorada
    • Ahora funciona con otros argumentos de línea de comando al buscar -parámetros anteriores.
Evan Kennedy
fuente
He estado buscando usar este método ya que me gustaría pasar argumentos a un archivo por lotes de esta manera. Sin embargo, noto que después de configurar las variables, incluso después de salir del archivo por lotes, los parámetros aún se establecen en el cmd si se accede y el lote ha finalizado, no se restauran a su estado anterior. ¿Debería este método manejar esa situación?
Jono_2007
Sobre el tema y mejor que algunas de las respuestas restantes en este hilo.
jwdonahue
Se extendió para admitir args de bandera (sin valores). Disculpe la falta de formato, pero no funciona en los comentarios: read_params si no% 1 / == / (si no es "% __ var%" == "" (si no es "% __ var: ~ 0,1%" == "-" (endlocal goto read_params) endlocal & set% __ var: ~ 1% =% ~ 1) else (setlocal & set __var =% ~ 1) shift goto read_params) else (si no es "% __ var%" == "" (endlocal & set% __ var: ~ 1% = 1))
Max
13

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
El Padrino
fuente
9

Para referirse a una variable establecida en la línea de comando, deberá usarla, %a%por ejemplo:

set a=100 
echo %a%  
rem output = 100 

Nota: Esto funciona para Windows 7 pro.

CMS_95
fuente
6

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 --fooque 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 --barque toma un valor requerido . Por último, puede tomar una bandera --bazsin 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
  • Use SETLOCALpara que las variables no escapen al entorno de llamada.
  • No olvide inicializar las variables SET FOO=, etc. en caso de que alguien las haya definido en el entorno de llamada.
  • Use %~1para eliminar comillas.
  • Use IF "%ARG%" == ""y no IF [%ARG%] == []porque [y ]no juegue tendrá valores que terminen en un espacio.
  • Incluso si está SHIFTdentro de un IFbloque, los argumentos actuales como %~1no se actualizan porque se determinan cuando IFse analiza. Podrías usar %~1y %~2dentro del IFbloque, pero sería confuso porque tenías un SHIFT. Puede poner el SHIFTal final del bloque para mayor claridad, pero eso podría perderse y / o confundir a las personas también. Así que "capturar" %~1y %~1fuera del bloque parece lo mejor.
  • No desea utilizar un parámetro en lugar del valor opcional de otro parámetro, por lo que debe verificarlo IF NOT "%ARG:~0,2%" == "--".
  • Tenga cuidado solo SHIFTcuando 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 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 --fooparámetro estaba presente como que %FOO%faltaba el valor.
  • Tenga en cuenta que ECHO Missing bar value. 1>&2enví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.
Garret Wilson
fuente
4

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...

SvenVP
fuente
Puede cerrar la ventana cmd después de que el proceso se haya cerrado utilizando el siguiente comando en un script por lotes:start /wait java %~n1
Paint_Ninja
1
Aconsejar al público que coloque archivos de script aleatorios en el directorio system32 es irresponsable. Esta respuesta realmente no raya la superficie del tema de este hilo.
jwdonahue
2

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.

Amol Patil
fuente
2

ingrese la descripción de la imagen aquí

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
No fui yo
fuente
1
Pero falla, cuando la contraseña contiene cualquier carácter de?*&<>
jeb
@jeb Gracias de nuevo, he agregado notas obs .: para responder hasta una nueva edición para manejar estos personajes ...
No fui yo