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ãoIF [%ARG%] == []
porque[
e]
não serão reproduzidos com valores que terminem em um espaço. - Mesmo se você
SHIFT
dentro de um blocoIF
, os argumentos atuais como%~1
não são atualizados porque são determinados quando oIF
é analisado. Você poderia usar%~1
e%~2
dentro do blocoIF
, mas seria confuso porque você tinha umSHIFT
. Você poderia colocar oSHIFT
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 umIF "%FOO%" == "" SET FOO=%DEFAULT_FOO%
fora do blocoIF NOT "%ARG%" == ""
. No entanto, como isso ainda está dentro do blocoIF "%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.