Como testar se existe um executável em% PATH% de um arquivo de lote do Windows?

89

Estou procurando uma maneira simples de testar se existe um executável na variável de ambiente PATH de um arquivo em lote do Windows.

O uso de ferramentas externas não fornecidas pelo sistema operacional não é permitido. A versão mínima do Windows necessária é o Windows XP.

Sorin
fonte
1
possível duplicata de Como verificar se um arquivo existe no lote DOS
karlphillip
15
@karlphilip: Definitivamente não. A questão aqui é bem diferente.
Joey
1
Você deve marcar uma resposta aceita.
Jeb

Respostas:

69
for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)
if defined FOUND ...

Se você precisar disso para extensões diferentes, apenas repita PATHEXT:

set FOUND=
for %%e in (%PATHEXT%) do (
  for %%X in (myExecutable%%e) do (
    if not defined FOUND (
      set FOUND=%%~$PATH:X
    )
  )
)

Pode ser que wheretambém já exista em versões legadas do Windows, mas não tenho acesso a uma, então não posso dizer. Na minha máquina também funciona o seguinte:

where myExecutable

e retorna com um código de saída diferente de zero se não puder ser encontrado. Em um lote, você provavelmente também deseja redirecionar a saída NUL.

Tenha em mente

A análise em .batarquivos batch ( ) e na linha de comando difere (porque os arquivos batch têm %0- %9), então você precisa dobrar o valor %. Na linha de comando isso não é necessário, portanto, as variáveis ​​são justas %X.

Joey
fonte
1
Gosto da sua abordagem, mas seria ainda melhor se você pudesse fornecer a versão completa, aquela que também usa PATHEXT para isso.
sorin
4
Para XP, você precisa do script de loop (ou baixe where.exe do RK). Vista e 7 vem com where.exe. Eu sei que o OP dizia especificamente XP, mas para a posteridade a melhor resposta é sempre usar where myExecutable.
Ryan Bemrose
Ryan: Hã? Eu não acho que posso analisar sua frase.
Joey
2
Sou um iniciante em scripts em lote e não tenho certeza do que significa %% x. No meu sistema Windows 7, tentei digitar: para %% X em (myExecutable.exe) do (defina FOUND = %% ~ $ PATH: X) e pressione retornado. Recebi isso em resposta: C: \ Users \ James> para %% X em (cmd.exe) do (definir FOUND = %% ~ $ PATH: X) %% X era inesperado neste momento.
simgineer
3
simengineer: a análise em arquivos em lote e na linha de comando difere (porque os arquivos em lote têm %0- %9), então você precisa dobrar o número %. Na linha de comando isso não é necessário, então as forvariáveis ​​são justas %x.
joey
79

O Windows Vista e as versões posteriores são fornecidos com um programa chamado where.exeque procura programas no caminho. Funciona assim:

D:\>where notepad
C:\Windows\System32\notepad.exe
C:\Windows\notepad.exe

D:\>where where
C:\Windows\System32\where.exe

Para uso em um arquivo em lote, você pode usar a /qopção, que apenas define ERRORLEVELe não produz nenhuma saída.

where /q myapplication
IF ERRORLEVEL 1 (
    ECHO The application is missing. Ensure it is installed and placed in your PATH.
    EXIT /B
) ELSE (
    ECHO Application exists. Let's go!
)

Ou uma versão abreviada simples (mas menos legível) que imprime a mensagem e sai do seu aplicativo:

where /q myapplication || ECHO Cound not find app. && EXIT /B
Ryan Bemrose
fonte
Muito bom e simples! Obrigado!
Pawel Cioch de
18

Aqui está uma solução simples que tenta executar o aplicativo e trata qualquer erro posteriormente .

file.exe /?  2> NUL
IF NOT %ERRORLEVEL%==9009 ECHO file.exe exists in path

O código de erro 9009 geralmente significa arquivo não encontrado.

A única desvantagem é que file.exeé realmente executado se for encontrado (o que em alguns casos não é desejável).

eadmaster
fonte
24
a única desvantagem é que "file.exe" é executado (o que em alguns casos é indesejado)
eadmaster
6

Isso pode ser feito por meio da substituição de parâmetros.

%~$PATH:1

Isso retorna o caminho completo do nome do arquivo executável em% 1, caso contrário, uma string vazia.

Isso não funciona com variáveis ​​definidas pelo usuário. Portanto, se o nome do arquivo executável não for um parâmetro para o seu script, você precisará de uma sub-rotina. Por exemplo:

call :s_which app.exe
if not "%_path%" == "" (
  "%_path%"
)

goto :eof

:s_which
  setlocal
  endlocal & set _path=%~$PATH:1
  goto :eof

Veja http://ss64.com/nt/syntax-args.html

Chris Noe
fonte
1
Truque interessante com, setlocalmas for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)é uma solução de linha forusada como solução alternativa para %%~$PATH:Xevitar calle %~$PATH:1.
gavenkoa
0
@echo off
set found=
set prog=cmd.exe
for %%i in (%path%) do if exist %%i\%prog% set found=%%i
echo "%found%"
if "%found%"=="" ....
PabloG
fonte
3
Não funcionará, pois fornão é inteligente o suficiente para analisar o conteúdo PATH. Irá perder diretórios com espaços, por exemplo. E mesmo quando você usa for /fcom delims=;ele não funcionará corretamente se um diretório contiver um ;e estiver entre aspas.
Joey
@Joey, que tal substituição de string? Substituir ;com "; ": set quotedPath="%PATH:;="; "%".
XP1
1
XP1: Não, ainda inútil. Experimente anexando "C:\Folder with; semicolon, quoted"ao caminho e veja o que acontece. Pelo menos aqui ele tenta tratar cada »palavra« separadamente o que, de certa forma, é pior do que o comportamento anterior.
Joey
0

Às vezes, essa solução simples funciona, na qual você verifica se a saída corresponde ao que você espera. A primeira linha executa o comando e pega a última linha da saída padrão.

FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.
bdombro
fonte
Mas e se o ambiente do sistema usar outro idioma?
Beachwalker
0

Se você está procurando algo como eu na pasta de inicialização, vá para a pasta. Por exemplo, procuro exe na pasta de inicialização e uso este código como

@echo off
cd C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp
where /q program.exe
IF ERRORLEVEL 1 (
echo F | xcopy /Y /S /I /E "\\programsetup\programsetup.exe" 
"C:\ProgramData\Microsoft\Windows\Start Menu\Programs\StartUp\program.exe"
) ELSE (
ECHO Application exists. Let's go!
)
Zafer ATLI
fonte
Mas isso procura no PATH completo se program.exeexiste, não apenas em uma pasta
jeb
-1

Use o comando: PowerShell Test-Path "exe que você está procurando"

Ele retornará True se estiver presente, caso contrário, False.

Akkidukes
fonte
Isso não vai funcionar. Test-Pathverifica apenas o caminho especificado, ou seja Test-Path nuget.exe, retornará verdadeiro apenas se nuget.exeestiver no diretório atual. Se nuget.exe não estiver no diretório atual, ele retornará falso, mesmo se estiver em um diretório listado na variável PATH. No PowerShell Get-Commandpode funcionar melhor ( stackoverflow.com/questions/11242368/… ), mas leve em consideração que para o PowerShell o diretório atual não está no caminho.
Ronald Zarīts de
1
Como @RonaldZarits apontou, para suporte total do PowerShell, você pode usar o Get-Command com duas opções. Primeiro forneça a localização do dir atual, depois apenas o nome do exe. (Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $nullretornará verdadeiro se for encontrado local ou no caminho.
John C
-1

Para quem procura uma opção PowerShell. Você pode usar o Get-Commandcmdlet passando dois itens. Primeiro forneça a localização dir atual com .\prefixado e, em seguida, forneça apenas o nome exe.

(Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $null

Isso retornará verdadeiro se for encontrado em caminhos locais ou em todo o sistema.

John C
fonte
Nada melhor do que downvote e run usuários. Se você discordar e for chegar a uma votação negativa, adicione também um comentário para explicar por que você discorda de que essa não é uma boa abordagem para obter os resultados desejados.
John C