Pergunta

Preciso passar um ID e uma senha para um arquivo em lote no momento da execução, em vez de codificá-los no arquivo.

Esta é a aparência da linha de comando:

test.cmd admin P@55w0rd > test-log.txt
Foi útil?

Solução 2

Veja como eu fiz isso:

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

Esta é a aparência do comando:

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

O %1 aplica-se ao primeiro parâmetro o %2 (e aqui está a parte complicada) se aplica ao segundo.Você pode ter até 9 parâmetros passados ​​desta forma.

Outras dicas

Outra dica útil é usar %* para significar "todos".Por exemplo:

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

Quando você corre:

test-command admin password foo bar

o arquivo em lote acima será executado:

fake-command /u admin /p password admin password foo bar

Posso estar com a sintaxe um pouco errada, mas esta é a ideia geral.

Se você deseja lidar de forma inteligente com os parâmetros ausentes, você pode fazer 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

Acessar parâmetros de lote pode ser simples com %1, %2, ...%9 ou também %*,
mas apenas se o conteúdo for simples.

Não existe uma maneira simples para conteúdos complexos como "&"^&, pois não é possível acessar %1 sem produzir um erro.

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

As linhas se expandem para

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

E cada linha falha, como um dos & está fora das aspas.

Isso pode ser resolvido lendo de um arquivo temporário um comentou versão do 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!'

O truque é ativar echo on e expanda o% 1 depois de um rem declaração (funciona também com %2 .. %*).
Então mesmo "&"& poderia ser ecoado sem produzir um erro, como é observado.

Mas para poder redirecionar a saída do echo on, você precisa dos dois loops for.

Os personagens extras * # são usados ​​para serem seguros contra conteúdos como /? (mostraria a ajuda para REM).
Ou um acento circunflexo ^ no final da linha poderia funcionar como um caractere multilinha, mesmo depois de um rem.

Então lendo o parâmetro rem saída do arquivo, mas com cuidado.
O for /f deve funcionar com uma expansão atrasada, caso contrário, conteúdo com "!" seria destruído.
Depois de remover os caracteres extras em param1, você entendeu.

E para usar param1 de forma segura, habilite a expansão atrasada.

Sim, e não se esqueça de usar variáveis ​​como %%1 ao usar if e for e a turma.

Se você esquecer o duplo %, então você substituirá argumentos de linha de comando (possivelmente nulos) e receberá algumas mensagens de erro bastante confusas.

Não há necessidade de complicar.É simplesmente o comando %1 %2 parâmetros, por exemplo,

@echo off

xcopy %1 %2 /D /E /C /Q /H /R /K /Y /Z

echo copied %1 to %2

pause

A "pausa" exibe o que o arquivo em lote fez e espera que você pressione a tecla QUALQUER.Salve como xx.bat na pasta Windows.

Para utilizá-lo, digite, por exemplo:

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

Este arquivo em lote cuida de todos os parâmetros necessários, como copiar apenas arquivos, que sejam mais recentes, etc.Eu o uso desde antes do Windows.Se você gosta de ver os nomes dos arquivos à medida que são copiados, deixe de fora o Q parâmetro.

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

Observação:SE "%1"=="" causará problemas se %1 está entre aspas.

Nesse caso, use IF [%1]==[] ou, apenas no NT 4 (SP6) e posterior, IF "%~1"=="" em vez de.

Um amigo me perguntou sobre esse assunto recentemente, então pensei em postar como lidar com argumentos de linha de comando em arquivos em lote.

Essa técnica tem um pouco de sobrecarga, como você verá, mas torna meus arquivos em lote muito fáceis de entender e rápidos de implementar.Além de apoiar as seguintes estruturas:

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

A essência disso é ter o :init, :parse, e :main funções.

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

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

Vamos manter isso simples.

Aqui está o arquivo .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%

Aqui estão três chamadas da linha 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
)

Isso percorre os parâmetros do lote (%*), estejam eles entre aspas ou não, e então ecoa cada parâmetro.

Eu escrevi um script read_params simples que pode ser chamado como uma função (ou externa .bat) e colocará todas as variáveis ​​no ambiente atual.Não modificará os parâmetros originais porque a função está sendo called com uma cópia dos parâmetros originais.

Por exemplo, dado o seguinte comando:

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

myscript.bat seria capaz de usar as variáveis ​​​​após chamar a função:

call :read_params %*

echo %random%
echo %greeting%

Aqui está a função:

: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

Limitações

  • Não é possível carregar argumentos sem valor, como -force.Você poderia usar -force=true mas não consigo pensar em uma maneira de permitir valores em branco sem conhecer antecipadamente uma lista de parâmetros que não terão valor.

Registro de alterações

  • 2/18/2016
    • Não requer mais expansão atrasada
    • Agora funciona com outros argumentos de linha de comando procurando por - antes dos parâmetros.

Para se referir a uma variável definida na linha de comando, você precisaria usar %a% então, por exemplo:

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

Observação:Isso funciona para o Windows 7 pro.

Crie um novo arquivo em lote (exemplo:openclass.bat) e escreva esta linha no arquivo:

java %~n1

Em seguida, coloque o arquivo em lote, digamos, na pasta system32, vá para o arquivo de classe Java, clique com o botão direito, Propriedades, Abrir com..., encontre seu arquivo em lote, selecione-o e pronto...

Funciona para mim.

PS:Não consigo encontrar uma maneira de fechar a janela do cmd ao fechar a classe Java.Por agora...

Inspirado por um responda em outro lugar por @Jon, criei um algoritmo mais geral para extrair parâmetros nomeados, valores opcionais e opções.

Digamos que queremos implementar um utilitário foobar.Requer um comando inicial.Possui um parâmetro opcional --foo que leva um opcional valor (que não pode ser outro parâmetro, claro);se o valor estiver faltando, o padrão é default.Também possui um parâmetro opcional --bar que leva um obrigatório valor.Por último, pode levar uma bandeira --baz sem valor permitido.Ah, e esses parâmetros podem vir em qualquer ordem.

Em outras palavras, fica assim:

foobar <command> [--foo [<fooval>]] [--bar <barval>] [--baz]

Aqui está uma solução:

@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 as variáveis ​​não escapem para o ambiente de chamada.
  • Não se esqueça de inicializar as variáveis SET FOO=, etc.caso alguém os tenha definido no ambiente de chamada.
  • Usar %~1 para remover aspas.
  • Usar IF "%ARG%" == "" e não IF [%ARG%] == [] porque [ e ] não brinque com valores que terminam em espaço.
  • Mesmo se você SHIFT dentro de um IF bloco, os argumentos atuais, como %~1 não são atualizados porque eles são determinados quando o IF é analisado.Você poderia usar %~1 e %~2 dentro de IF bloco, mas seria confuso porque você tinha um SHIFT.Você poderia colocar o SHIFT no final do bloco para maior clareza, mas isso pode se perder e/ou confundir as pessoas também.Então "capturar" %~1 e %~1 fora do quarteirão parece melhor.
  • Você não deseja usar um parâmetro no lugar do valor opcional de outro parâmetro, então você deve verificar IF NOT "%ARG:~0,2%" == "--".
  • Tenha cuidado apenas para SHIFT quando você usar um dos parâmetros.
  • O código duplicado SET FOO=%DEFAULT_FOO% é lamentável, mas a alternativa seria acrescentar uma IF "%FOO%" == "" SET FOO=%DEFAULT_FOO% fora da IF NOT "%ARG%" == "" bloquear.No entanto, porque isso ainda está dentro do IF "%PARAM%" == "--foo" bloco, o %FOO% valor teria sido avaliado e definido antes de você entrar no bloco, então você nunca detectaria isso ambos o --foo parâmetro estava presente e também que o %FOO% faltou valor.
  • Observe que ECHO Missing bar value. 1>&2 envia a mensagem de erro para stderr.
  • Quer uma linha em branco em um arquivo em lote do Windows?Você tem que usar ECHO: ou uma das variações.

Solução simples (mesmo que a questão seja antiga)

Teste1.bat

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

CallTest1.bat

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

saída

YourLocalPath>call "C:\Temp\test.bat" pass123

YourLocalPath>echo off
"Batch started"
"arg1 is pass123"

YourLocalPath>pause
Press any key to continue . . .

Onde YourLocalPath é o caminho do diretório atual.

Para manter as coisas simples, armazene o parâmetro de comando na variável e use a variável para comparação.

Não é apenas simples de escrever, mas também de manter, então se mais tarde alguma outra pessoa ou você ler seu roteiro após um longo período de tempo, será fácil de entender e manter.

Para escrever código embutido:veja outras respostas.

enter image description here

Para usar o loop, obtenha todos os argumentos e em lote puro:

@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 

Seu código está pronto para fazer algo com o número do argumento onde for necessário, 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 em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top