Pregunta

Necesito pasar una identificación 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
¿Fue útil?

Solución 2

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 %1 se aplica al primer parámetro el %2 (y aquí está la parte complicada) se aplica al segundo.Puede pasar hasta 9 parámetros de esta manera.

Otros consejos

Otro consejo útil es utilizar %* que significa "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 tenga un poco de sintaxis incorrecta, pero esta es la idea general.

Si desea manejar de forma inteligente los parámetros faltantes, 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 sencillo con %1, %2, ...%9 o también %*,
pero sólo si el contenido es simple.

No existe una forma sencilla para contenidos complejos como "&"^&, ya que no es posible acceder a %1 sin que se produzca 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, como uno de los & está fuera de las comillas.

Se puede solucionar leyendo desde un archivo temporal un comentó versión 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 consiste en habilitar echo on y expandir el %1 después de un rem declaración (funciona también con %2 .. %*).
Aun asi "&"& podría repetirse sin producir un error, como se observa.

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

Los personajes adicionales * # se utilizan para estar seguros contra contenidos como /? (Mostraría la ayuda para REM).
O un signo de intercalación ^ al final de la línea podría funcionar como un carácter de varias líneas, incluso después de un rem.

Luego leyendo el parámetro remoto salida del archivo, pero con cuidado.
El para /f debería funcionar con expansión retrasada, de lo contrario, contenido con "!" sería destruido.
Después de eliminar los caracteres adicionales en param1, lo entendiste.

y para usar param1 de forma segura, habilitar la expansión retrasada.

Sí, y no olvides usar variables como %%1 cuando usas if y for y la pandilla.

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

No hay necesidad de complicarlo.Es simplemente el 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 presione CUALQUIER tecla.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 encarga de todos los parámetros necesarios, como copiar sólo archivos, que sean más nuevos, etc.Lo he usado desde antes de Windows.Si desea ver los nombres de los archivos a medida que se copian, omita el Q parámetro.

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

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

En ese caso, utilice IF [%1]==[] o, en NT 4 (SP6) y posteriores únicamente, IF "%~1"=="" en cambio.

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.

Esta técnica tiene un poco de complejidad, como verá, 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][...]

Lo esencial es tener la :init, :parse, y :main funciones.

Uso de ejemplo

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

plantilla.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 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, luego repite cada parámetro.

Escribí un script read_params simple 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 está siendo called 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 utilizar 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ías usar -force=true pero no se me ocurre una manera de permitir valores en blanco sin conocer de antemano una lista de parámetros que no tendrán un valor.

Registro de cambios

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

Para hacer referencia a una variable establecida en la línea de comando, necesitaría usar %a% así por ejemplo:

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

Nota:Esto funciona para Windows 7 pro.

Cree un nuevo archivo por lotes (ejemplo:openclass.bat) y escribe 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 en Propiedades, Abrir con..., luego busque su archivo por lotes, selecciónelo y listo...

Esto funciona para mi.

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

Inspirado por un responder en otro lugar Por @Jon, he creado un algoritmo más general para extraer parámetros con nombre, valores opcionales y modificadores.

Digamos que queremos implementar una utilidad. foobar.Requiere un comando inicial.Tiene un parámetro opcional --foo que toma un opcional valor (que no puede ser otro parámetro, claro);si falta el valor, el valor predeterminado es default.También tiene un parámetro opcional. --bar que toma un requerido valor.Por último puede llevar una bandera. --baz sin valor permitido.Ah, y estos parámetros pueden aparecer 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
  • Usar SETLOCAL para que las variables no escapen al entorno de llamada.
  • No olvides inicializar las variables. SET FOO=, etc.en caso de que alguien los haya definido en el entorno de llamada.
  • Usar %~1 para eliminar comillas.
  • Usar IF "%ARG%" == "" y no IF [%ARG%] == [] porque [ y ] No juegues en absoluto con valores que terminen en un espacio.
  • Incluso si tú 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 de IF bloquear, pero sería confuso porque tenías un SHIFT.Podrías poner el SHIFT al final del bloque para mayor claridad, pero eso podría perderse y/o confundir a la gente también.Entonces "capturar" %~1 y %~1 fuera del bloque parece 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 sólo con SHIFT Cuando usted usar uno de los parámetros.
  • El código duplicado SET FOO=%DEFAULT_FOO% Es lamentable, pero la alternativa sería añadir una IF "%FOO%" == "" SET FOO=%DEFAULT_FOO% afuera de IF NOT "%ARG%" == "" bloquear.Sin embargo, debido a que esto todavía está dentro del IF "%PARAM%" == "--foo" bloque, el %FOO% El valor se habría evaluado y establecido antes de ingresar al bloque, por lo que nunca detectaría ese ambos el --foo el parámetro estaba presente y también que el %FOO% faltaba valor.
  • Tenga en cuenta que ECHO Missing bar value. 1>&2 envía el mensaje de error a stderr.
  • ¿Quiere una línea en blanco en un archivo por lotes de Windows?tienes que usar ECHO: o una de las variaciones.

Solución simple (aunque la pregunta es antigua)

Prueba1.bat

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

LlamadaTest1.bat

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

producción

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 del directorio actual.

Para simplificar las cosas, almacene el parámetro de comando en variable y use la variable para comparar.

No sólo es fácil de escribir, sino también de mantener, por lo que si más adelante 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:ver otras respuestas.

enter image description here

Para utilizar el bucle, obtenga todos los argumentos y en lotes puros:

@echo off && setlocal EnableDelayedExpansion

 set "_cnt=0" && for %%Z in (%*) do ( 
 set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
 shift && 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 sea necesario, como...

 @echo off && setlocal EnableDelayedExpansion

 set "_cnt=0" && for %%Z in (%*) do ( 
 set "_arg_=%%Z" && set /a "_cnt=!_cnt! + 1" && set "_arg_[!_cnt!]=!_arg_!"
 shift 

 )

 fake-command /u !_arg_[1]! /p !_arg_[2]! > test-log.txt
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top