Como posso verificar se um argumento é definido ao iniciar / chamar um arquivo em lote?

96

Estou tentando usar a seguinte lógica de validação em um arquivo em lote, mas o bloco "uso" nunca é executado, mesmo quando nenhum parâmetro é fornecido ao arquivo em lote.

if ("%1"=="") goto usage

@echo This should not execute

@echo Done.
goto :eof

:usage
@echo Usage: %0 <EnvironmentName>
exit 1

O que estou fazendo de errado?

Daniel Fortunov
fonte

Respostas:

146

A verificação para saber se um argumento de linha de comando foi definido pode ser [%1]==[], mas, como Dave Costa aponta , "%1"==""também funcionará.

Também consertei um erro de sintaxe no eco de uso para escapar dos sinais de maior e menor. Além disso, o exitprecisa de um /Bargumento, caso contrário CMD.exeserá encerrado.

@echo off

if [%1]==[] goto usage
@echo This should not execute
@echo Done.
goto :eof
:usage
@echo Usage: %0 ^<EnvironmentName^>
exit /B 1
Iain
fonte
18
[% 1] == [] é melhor do que "% 1" == "" porque tratará corretamente o caso em que o próprio% 1 contém aspas duplas. "% 1" == "" apresentará um erro com uma mensagem "inesperado neste momento".
tekumara
2
Observe que, se você não estiver usando argumentos de linha de comando, mas setvariáveis ​​(não sei a terminologia de lote correta), você pode querer usar "%myvar%"==""porque se myvarcontiver espaços e não estiver entre aspas, você obterá o "inesperado neste momento " mensagem.
Pat
1
Variáveis ​​@Pat SET podem ser verificadas com IF NOT DEFINED VarNamebloco. Também +1 para tukushan por não usar aspas na comparação. Só não faça isso. Nunca.
Fr0sT de
10
"%~1"==""também funcionará e cuidará do caso em que% 1 tem aspas duplas
Drakkim
8
"%~1"==""lida com espaços na variável, enquanto a []versão não.
Cookie Butter de
17

Um exemplo mais avançado:

⍟ argumentos ilimitados.

⍟ existe no sistema de arquivos ( fileou directory?) Ou genérico string.

⍟ especifique se é um arquivo

⍟ especificar é um diretório

sem extensões, funcionaria em scripts legados!

código mínimo ☺

@echo off

:ciclo
      :: -------------------------- tem argumento?
      if ["% ~ 1"] == [""] (
        eco feito.
        ir para o fim
      )
      :: -------------------------- existe argumento?
      se não existir% ~ s1 (
        eco não existe
      ) outro (
        eco existe
        se existir% ~ s1 \ NUL (
          echo é um diretório
        ) outro (
          echo é um arquivo
        )
      )
      :: --------------------------
      mudança
      goto loop
      
      
:fim

pausa

✨ outras coisas..✨

■ em %~1- ~remove qualquer embalagem "ou '.

■ in %~s1- o storna o caminho DOS 8.3 naming, que é um bom truque para evitar espaços no nome do arquivo ao verificar as coisas (e desta forma não há necessidade de envolver o recurso com mais "s.

■ o ["%~1"]==[""]"não posso ter certeza" se o argumento é um arquivo / diretório ou apenas uma string genérica, então, em vez disso, a expressão usa colchetes e o original não modificado %1(apenas sem a "quebra, se houver ..)

se não houver argumentos de se usamos shifte o ponteiro da lista de argumentos passou o último, a expressão será avaliada como [""]==[""].

■ isso é o mais específico que você pode ser sem usar mais truques (funcionaria mesmo em scripts em lote do Windows 95 ...)

■ exemplos de execução

salve como identifier.cmd

ele pode identificar argumentos ilimitados (normalmente você está limitado a %1- %9), apenas lembre-se de envolver os argumentos com vírgulas invertidas, ou usar a nomenclatura 8.3, ou arrastar e soltar (automaticamente faz qualquer um dos itens acima).


isso permite que você execute os seguintes comandos:

identifier.cmd c:\windows e para obter

existir
é um diretório
feito

identifier.cmd "c:\Program Files (x86)\Microsoft Office\OFFICE11\WINWORD.EXE" e para obter

existir
é um arquivo
feito

⓷ e vários argumentos (claro que isso é tudo ..)

identifier.cmd c:\windows\system32 c:\hiberfil.sys "c:\pagefile.sys" hello-world

e para obter

existir
é um diretório
existir
é um arquivo
existir
é um arquivo
não existe
feito.

naturalmente, pode ser muito mais complexo, mas bons exemplos devem ser sempre simples e mínimos. :)

Espero que ajude alguém :)

publicado aqui: CMD Ninja - processamento ilimitado de argumentos, identificando se existe no sistema de arquivos, identificando se o arquivo ou diretório

e aqui está um exemplo de trabalho que pega qualquer quantidade de arquivos APK (aplicativos Android) e os instala em seu dispositivo por meio do console de depuração (ADB.exe): Torne a postagem anterior um instalador de APK em massa que não usa a sintaxe de instalação múltipla ADB

Comunidade
fonte
14

Livre-se dos parênteses.

Arquivo de lote de amostra:

echo "%1"

if ("%1"=="") echo match1

if "%1"=="" echo match2

Resultado da execução do script acima:

C:\>echo "" 
""

C:\>if ("" == "") echo match1 

C:\>if "" == "" echo match2 
match2

Acho que os parênteses são parte das cordas e eles estão sendo comparados.

Dave Costa
fonte
1
if "%1"==""irá travar se o arg tiver espaços. Por exemplo: run.bat "a b". @amr tem a melhor resposta para usarif "%~1"==""
wisbucky
6
IF "%~1"=="" GOTO :Usage

~ irá retirar as cotações de% 1 se o próprio% 1 for citado.

"" protegerá contra caracteres especiais passados. por exemplo, chamando o script com & ping

Amr Ali
fonte
1
Esta é a melhor resposta. As outras respostas funcionam para alguns casos, mas falharão para casos mais especiais comorun.bat "a b"
wisbucky
@wisbucky Isso não parece atrapalhar a resposta aceita . o que estou perdendo?
ruffin
@ruffin, Exemplo: run.bat ""não será pego por [%1]==[].
wisbucky
2
IF "%1"=="" GOTO :Continue
.....
.....
:Continue
IF "%1"=="" echo No Parameter given
Howard Rothenburg
fonte
Isso falha pararun.bat "a b"
wisbucky
2

Esta é a mesma que as outras respostas, mas usa apenas um rótulo e coloca o uso em primeiro lugar, o que adicionalmente faz com que sirva como uma espécie de recomendação de documentação do script que também é normalmente colocado no topo:

@echo off
:: add other test for the arguments here...
if not [%1]==[] goto main
:: --------------------------
echo This command does something.
echo.
echo %0 param%%1 param%%2
echo       param%%1 the file to operate on
echo       param%%1 another file

:: --------------------------
exit /B 1

:main
:: --------------------------
echo do something with all arguments (%%* == %*) here...

No entanto, se você não precisa usar cmd / batch, use bash em WSL ou powershell, eles têm uma sintaxe mais sã e menos recursos misteriosos.

masterxilo
fonte
0

SE "% 1" == "" falhar, todas as versões falharão sob certas condições de personagem envenenado. Somente IF DEFINED ou IF NOT DEFINED são seguros

codey
fonte
if [not] defined ...não funciona com parâmetros como %1. Você tem um exemplo, onde if "%~1" ...não funciona?
Stephan