Determinar se o comando é reconhecido em um arquivo em lotes

43

Estou escrevendo um script bat no qual invoco um programa (como javac). Para simplificar, quero verificar se o comando existe antes de executá-lo. ou seja, se o comando existe no PATH.

Por exemplo,

if (my_command.exe is a recognized command) then (
  my_command.exe my_args
) else (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file."
  REM Do not run my_command.exe
)

Qual é a melhor maneira de fazer isso no Windows?

user46097
fonte
Como você "reconhecerá" seu comando?
Rook
No MS-DOS (verdadeiro DOS) isso era bastante simples; você acabou de verificar a existência de um arquivo exe em c: \ dos; mas mesmo assim a questão permanece.
Rook
Desculpe pela confusão. Eu quis dizer essencialmente um prompt de comando no Windows. Se eu digitar "lkajsflksajdfj", quero detectar que não é um comando. Se eu digitar "notepad.exe", tudo bem.
user46097

Respostas:

54
WHERE mycommand
IF %ERRORLEVEL% NEQ 0 ECHO mycommand wasn't found 
Josh Santangelo
fonte
10
Se alguém não quiser a saída dentro da janela do cmd, basta adicionar >nul 2>nulatrás do mycommand.
Sebastian
Observe que existem mais canais de saída que 1 e 2, já que 1 representa buffer de saída e 2 representa buffer de erro, depende de como o aplicativo foi desenvolvido; ele deve funcionar para aplicativos comuns fornecidos com o Windows, mas um programa CLI específico pode ainda está jogando texto quando os canais 1 e 2 são redirecionados.
ElektroStudios
15

O código abaixo deve sempre ser executado de forma limpa, sem saída de lixo.

javac -version >nul 2>&1 && (
    echo found javac
) || (
    echo fail
)

Saída:

found javac

O mesmo código de uma linha:

javaz -version >nul 2>&1 && ( echo found javac ) || ( echo fail )

Saída:

fail

Observe que a ordem &&e ||parece importar. Além disso, o comando cuja existência você está testando precisa retornar com um nível de erro <= 0 para que isso funcione. Espero que o comando tenha /? ou --help argumentos ou, como no java, um comando de informações da versão.

ngreen
fonte
Esta solução é perfeita!
robe007 8/07
7

A maneira mais fácil é simplesmente executar o comando, mas isso tem outros problemas, é claro, pois talvez você não queira iniciar um processo aleatório.

for %%x in (my_command.exe) do if not [%%~$PATH:x]==[] set MyCommandFound=1

é uma alternativa que procura o programa nos caminhos listados pela %PATH%variável de ambiente. É essencialmente uma versão em lote pura do which(1). Pode ser melhorado, mas essencialmente é isso.

Joey
fonte
11
Isso é perfeito, faz exatamente o que foi solicitado!
Pez Cuckow
3

Para a minha situação. A maneira mais simples e absoluta é usar o || ou operador &&.

my_command.exe -version 2>NUL && echo "my_command exists"

ou

my_command.exe -version 2>NUL || echo "my_command doesn't exist"
user46097
fonte
Por que você também não redireciona o stdout?
Joey
3

Alguns refinamentos para a versão abaixo. Teste esse comando e suprima a saída desnecessária.

WHERE scp >nul 2>nul
IF %ERRORLEVEL% EQU 0 ECHO scp found
yuliskov
fonte
onde <my_exe> NUL 2> & 1 || echo my.exe não existe & goto: EOF funciona bem em scripts
Robert
Nota: isso não funciona se o nome do arquivo que você deseja testar incluir informações de caminho. Por exemplo, WHERE \Windows\System32\cmd.exe=>INFO: Could not find files for the given pattern(s).
Jonathan Gilbert
1

Se a solicitação da instalação de ferramentas extras estiver correta, há um wherecomando nos kits de recursos; veja Windows equivalente de whereis? .

Caso contrário, para versões do Windows que não são muito antigas, é possível fazê-lo em puro cmd, conforme mencionado em Pesquisa executável do Dos, exceto PATH .

Gilles 'SO- parar de ser mau'
fonte
Obrigado pela resposta! Infelizmente, um dos requisitos é que ele tenha que ser executado em uma caixa de baunilha (incluindo máquinas XP) - portanto, isso não é uma opção.
user46097
2
O segundo link fornecido por Gilles tem uma solução bacana que usa FOR e nenhuma ferramenta extra.
Paradroid
1

Sei que isso não é exatamente o que você está procurando, mas com uma ligeira mudança na lógica, ele deve realizar o que você precisa.

Todo comando executado tem um código de retorno (também conhecido como errorlevel); se o código de retorno for 0 (zero), o comando foi executado com sucesso; se o código de retorno for maior que 0, algo deu errado.

Veja aqui para mais detalhes.

Algo como -

my_command
if (%ERRORLEVEL% > 0) then (
  REM Output was probably "'my_command.exe' is not recognized as an internal or external command, operable program or batch file.  OR SOMETHING WENT WRONG WITH IT."
  REM Do not run my_command.exe
)
bryan
fonte
Isso é inteligente, eu gosto.
Shinrai 13/08/10
Sim, mas é feio desde que, se o comando não for encontrado, ele gera um erro de 2 linhas. Assim, uma solução mais limpa poderia ser encontrada possivelmente.
djangofan
0

Embora todo esse caminho possa funcionar, por que não o construído de maneira?

If exists my_command do echo "my_command exists"

Execute "se /?" na linha de comando para obter detalhes

uSlackr
fonte
5
Isso examinará apenas se um arquivo / diretório com esse nome existe no diretório atual. Ele não fornece muita dica sobre a existência de um comando executável com esse nome, pois para determinar se você precisaria pesquisar no PATH.
Joey #: