Usando parâmetros em arquivos em lotes na linha de comando do Windows

161

No Windows, como você acessa os argumentos passados ​​quando um arquivo em lotes é executado?

Por exemplo, digamos que eu tenho um programa chamado hello.bat. Quando entro hello -aem uma linha de comando do Windows, como faço para informar meu programa que -afoi passado como argumento?

Uma pessoa
fonte
Como passar parâmetros de linha de comando para um arquivo de lote: stackoverflow.com/questions/26551/...
Eric Leschinski
3
Ele menciona "linha de comando do DOS".
precisa saber é o seguinte

Respostas:

287

Como já foi dito, os parâmetros passados ​​pela linha de comando podem ser acessados ​​em arquivos em lotes com a notação %1para %9. Há também outros dois tokens que você pode usar:

  • %0é o nome do arquivo executável (arquivo em lote), conforme especificado na linha de comando .
  • %*são todos os parâmetros especificados na linha de comando - isso é muito útil se você deseja encaminhar os parâmetros para outro programa.

Também há muitas técnicas importantes a serem observadas, além de simplesmente como acessar os parâmetros.

Verificando se um parâmetro foi passado

Isso é feito com construções como IF "%~1"=="", o que é verdadeiro se e somente se nenhum argumento foi passado. Observe o caractere til que faz com que as aspas circundantes sejam removidas do valor de %1; sem um til, você obterá resultados inesperados se esse valor incluir aspas duplas, incluindo a possibilidade de erros de sintaxe.

Lidar com mais de 9 argumentos (ou apenas facilitar a vida)

Se você precisar acessar mais de 9 argumentos que você tem que usar o comando SHIFT. Este comando altera os valores de todos os argumentos em um único lugar, de modo que %0assume o valor de %1, %1assume o valor de %2etc. %9assume o valor do décimo argumento (se houver algum), que não estava disponível por meio de nenhuma variável antes de chamar SHIFT(digite comando SHIFT /?para mais opções).

SHIFTtambém é útil quando você deseja processar facilmente parâmetros sem exigir que eles sejam apresentados em uma ordem específica. Por exemplo, um script pode reconhecer os sinalizadores -ae -bem qualquer ordem. Uma boa maneira de analisar a linha de comando nesses casos é

:parse
IF "%~1"=="" GOTO endparse
IF "%~1"=="-a" REM do something
IF "%~1"=="-b" REM do something else
SHIFT
GOTO parse
:endparse
REM ready for action!

Esse esquema permite analisar linhas de comando bastante complexas sem enlouquecer.

Substituição de parâmetros de lote

Para parâmetros que representam nomes de arquivos, o shell fornece muitas funcionalidades relacionadas ao trabalho com arquivos que não são acessíveis de nenhuma outra maneira. Essa funcionalidade é acessada com construções que começam com %~.

Por exemplo, para obter o tamanho do arquivo passado como argumento, use

ECHO %~z1

Para obter o caminho do diretório de onde o arquivo em lotes foi iniciado (muito útil!), Você pode usar

ECHO %~dp0

Você pode visualizar toda a gama desses recursos digitando CALL /?no prompt de comando.

Jon
fonte
4
A construção: parse,: endparse é beleza, mesmo com o GOTO. Obrigado! (Quero dizer, o DOS-BASIC forçou o GOTO)
mmrtnt
1
Essa técnica pode falhar ao chamar o BAT do PowerShell. Um argumento citado como "name=John"se tornará name Johndurante exe. A solução é surround com aspas simples,'"name=John"'
cmcginty
1
Como eu passei tanto tempo sem isso CALL /?? Aqui, eu ando brincando com o Google o tempo todo.
bigtlb
@Jon: Eu escrevi o arquivo bat que contém apenas um código echo% 1 se eu o chamar via cmd, por exemplo, xx.bat & parameter> "C: \ yy.txt" chamando o arquivo bat com parâmetro e escrevendo no arquivo txt, mas se eu der & no parâmetro no início ou no final, não está funcionando. Qualquer outro texto funcionando bem.
Alex Mathew
56

Usando parâmetros em arquivos em lote:% 0 e% 9

Os arquivos em lote podem se referir às palavras passadas como parâmetros com os tokens: %0to %9.

%0 is the program name as it was called.
%1 is the first command line parameter
%2 is the second command line parameter
and so on till %9.

os parâmetros passados ​​na linha de comando devem ter caracteres alfanuméricos e delimitados por espaços. Como %0é o nome do programa como foi chamado, o DOS %0estará vazio para o AUTOEXEC.BAT se iniciado no momento da inicialização.

Exemplo:

Coloque o seguinte comando em um arquivo em lotes chamado mybatch.bat:

@echo off
@echo hello %1 %2
pause

Invocar o arquivo em lotes como este: mybatch john billyproduziria:

hello john billy

Obtenha mais de 9 parâmetros para um arquivo em lotes, use:% *

O símbolo de Porcentagem em estrela %*significa "o restante dos parâmetros". Você pode usar um loop for para capturá-los, conforme definido aqui:

http://www.robvanderwoude.com/parameters.php

Notas sobre delimitadores para parâmetros em lote

Alguns caracteres nos parâmetros da linha de comando são ignorados pelos arquivos em lotes, dependendo da versão do DOS, sejam "escapados" ou não, e geralmente dependendo da localização na linha de comando:

commas (",") are replaced by spaces, unless they are part of a string in 
double quotes

semicolons (";") are replaced by spaces, unless they are part of a string in 
double quotes

"=" characters are sometimes replaced by spaces, not if they are part of a 
string in double quotes

the first forward slash ("/") is replaced by a space only if it immediately 
follows the command, without a leading space

multiple spaces are replaced by a single space, unless they are part of a 
string in double quotes

tabs are replaced by a single space

leading spaces before the first command line argument are ignored
Eric Leschinski
fonte
5

Os arquivos em lote passam automaticamente o texto após o programa, desde que sejam variáveis ​​para atribuí-los. Eles são passados ​​na ordem em que são enviados; por exemplo,% 1 será a primeira string enviada após o programa ser chamado, etc.

Se você possui o Hello.bat e o conteúdo é:

@echo off
echo.Hello, %1 thanks for running this batch file (%2)
pause

e você invoca o lote no comando via

hello.bat APerson241% date%

você deve receber esta mensagem de volta:

Olá, APerson241 obrigado por executar este arquivo em lotes (01/11/2013)

rud3y
fonte
4

O esquema de Jon :parse/ :endparseé um ótimo começo, e ele tem minha gratidão pelo passe inicial, mas se você acha que o sistema de lotes torturantes do Windows deixaria você tão fácil ... bem, meu amigo, você está em choque. Passei o dia inteiro com esse diabo e, depois de muitas pesquisas e experimentações dolorosas, finalmente consegui algo viável para um utilitário da vida real.

Digamos que queremos implementar um utilitário foobar. Requer um comando inicial. Tem um parâmetro opcional --fooque aceita 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 --barque aceita um valor necessário . Por fim, pode receber uma bandeira --bazsem valor permitido. Ah, e esses parâmetros podem vir em qualquer ordem.

Em outras palavras, fica assim:

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

Complicado? Não, isso parece bastante típico dos utilitários da vida real. ( gitalguém?)

Sem mais delongas, 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

Sim, é realmente tão ruim assim. Veja meu post semelhante em https://stackoverflow.com/a/50653047/421049 , onde forneço mais análises do que está acontecendo na lógica e por que usei certas construções.

Medonho. A maioria disso eu tive que aprender hoje. E doeu.

Garret Wilson
fonte
3

Use variáveis, ou seja, as .BATvariáveis ​​e chamadas %0para%9

tohava
fonte