ss64 - windows batch file documentation




Como faço para passar parâmetros de linha de comando para um arquivo em lotes? (10)

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 há um caminho simples para conteúdos complexos como "&"^& , já que 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, pois uma das & está fora das aspas.

Ele pode ser resolvido com a leitura de um arquivo temporário de uma versão comentada 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 o echo on e expandir o% 1 após uma instrução rem (funciona também com %2 .. %* ).
Assim, mesmo "&"& poderia ser reproduzido sem produzir um erro, como é observado.

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

Os caracteres extras * # são usados ​​para proteção contra conteúdos como /? (mostraria a ajuda para REM ).
Ou um careta no final da linha poderia funcionar como um caractere multilinha, mesmo depois de um rem .

Em seguida, lendo o parâmetro rem saída do arquivo, mas com cuidado.
O FOR / F deve funcionar com a expansão atrasada desativada, senão o conteúdo com "!" seria destruído.
Depois de remover os caracteres extras no param1 , você conseguiu.

E para usar o param1 maneira segura, ative a expansão atrasada.

Eu preciso passar id e senha para um arquivo cmd (ou bat) no momento da execução, em vez de codificá-los no arquivo.

Aqui está o que a linha de comando parece:

test.cmd admin [email protected] > test-log.txt

Aqui está como eu faço isso.

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

Aqui está o que a linha de comando parece:

test.cmd admin [email protected] > test-log.txt

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


Faça um novo arquivo de lote (exemplo: openclass.bat) e escreva esta linha no arquivo:

java %~n1

Em seguida, coloque o arquivo de lote na pasta system32, vá para o arquivo de classe Java, clique com o botão direito, Properties, Open with ..., encontre o arquivo de lote, selecione-o e pronto ...

Funciona para mim.

PS: Eu não consigo encontrar uma maneira de fechar a janela do cmd quando fecho a classe Java. Para agora...


Inspirado por uma resposta em outro lugar de @Jon, criei um algoritmo mais geral para extrair parâmetros nomeados, valores opcionais e comutadores.

Vamos dizer que queremos implementar um utilitário foobar . Requer um comando inicial. Ele tem um parâmetro opcional --foo que recebe um valor opcional (que não pode ser outro parâmetro, é claro); se o valor estiver ausente, o padrão será default . Ele também possui um parâmetro opcional --bar que recebe um valor requerido . Por fim, pode levar uma bandeira --baz sem valor permitido. Ah, e esses parâmetros podem vir em qualquer ordem.

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

Outra dica útil é usar %* para significar "all". 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 de lote acima será executado:

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

Eu posso ter a sintaxe um pouco errada, mas esta é a idéia geral.


Para se referir a uma variável set na linha de comando, você precisaria usar "% a%", por exemplo:

      set a=100 
      echo %a%  
      output = 100 

Nota: Isso funciona para o Windows 7 pro.


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

Se você esquecer o double % , então você estará substituindo (possivelmente nulo) argumentos de linha de comando e receberá algumas mensagens de erro bastante confusas.


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

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

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 comando param na variável e use a variável para comparação.

Não é apenas simples de escrever, mas é simples de manter, assim, se mais tarde, outra pessoa ou você ler o seu script depois de um longo período de tempo, será fácil de entender e manter.

Para escrever código em linha: veja outras respostas.


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

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

Nota: SE "%1"=="" causará problemas se %1 estiver entre aspas.

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





cmd