Как проверить, существует ли исполняемый файл в% PATH% из командного файла Windows?

90

Я ищу простой способ проверить, существует ли исполняемый файл в переменной среды PATH из командного файла Windows.

Использование внешних инструментов, не предусмотренных ОС, не допускается. Минимальная необходимая версия Windows - Windows XP.

Сорин
источник
1
возможный дубликат Как проверить, существует ли файл в пакете DOS
Карлфиллип
16
@karlphilip: Определенно нет. Здесь вопрос совсем другой.
Joey
1
Вы должны отметить принятый ответ.
Джеб,

Ответы:

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

Если вам это нужно для разных расширений, просто повторите PATHEXT:

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

Возможно, он whereуже существует в устаревших версиях Windows, но у меня нет доступа к нему, поэтому я не могу сказать. На моей машине также работает следующее:

where myExecutable

и возвращается с ненулевым кодом выхода, если его не удалось найти. Однако в пакете вы, вероятно, также захотите перенаправить вывод в NUL.

Иметь ввиду

Разбор в .batфайлах batch ( ) и в командной строке отличается (потому что в пакетных файлах есть %0- %9), поэтому вам нужно удвоить %там. В командной строке это не обязательно, поэтому для переменных просто %X.

Джоуи
источник
1
Мне нравится ваш подход, но было бы еще лучше, если бы вы могли предоставить полную версию, которая также использует для этого PATHEXT.
sorin
4
Для XP нужен скрипт цикла (или скачать where.exe из РК). Vista и 7 поставляются с where.exe. Я знаю, что OP конкретно сказал XP, но для потомков лучший ответ - всегда использовать where myExecutable.
Райан Бемроуз
Райан: А? Я не думаю, что смогу разобрать ваше предложение.
Joey
2
Я начинаю писать сценарии и не знаю, что означает %% x. В моей системе Windows 7 я попытался ввести: для %% X в (myExecutable.exe) сделайте (установите FOUND = %% ~ $ PATH: X), а затем нажмите Return. Я получил это в ответ: C: \ Users \ James> для %% X в (cmd.exe) do (set FOUND = %% ~ $ PATH: X) %% X было неожиданным в это время.
simgineer 05
3
simengineer: синтаксический анализ в пакетных файлах и в командной строке отличается (потому что пакетные файлы имеют %0- %9), поэтому вам нужно удвоить %там. В командной строке в этом нет необходимости, поэтому используются forпеременные %x.
Joey
82

Windows Vista и более поздние версии поставляются с программой, where.exeкоторая ищет программы в пути. Это работает так:

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

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

Для использования в пакетном файле вы можете использовать /qпереключатель, который просто устанавливает ERRORLEVELи не производит никакого вывода.

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!
)

Или простая (но менее читаемая) сокращенная версия, которая печатает сообщение и закрывает ваше приложение:

where /q myapplication || ECHO Cound not find app. && EXIT /B
Райан Бемроуз
источник
Очень красиво и просто! Благодаря!
Павел Чох
18

Вот простое решение, которое пытается запустить приложение и впоследствии обрабатывает любые ошибки .

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

Код ошибки 9009 обычно означает, что файл не найден.

Единственным недостатком является то, что file.exeфактически выполняется, если он найден (что в некоторых случаях нежелательно).

eadmaster
источник
25
Единственным недостатком является то, что запускается «file.exe» (что в некоторых случаях нежелательно)
eadmaster
6

Это можно сделать с помощью подстановки параметров.

%~$PATH:1

Это возвращает полный путь к исполняемому файлу в% 1 или пустую строку.

Это не работает с пользовательскими переменными. Поэтому, если имя исполняемого файла не является параметром вашего скрипта, вам нужна подпрограмма. Например:

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

goto :eof

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

См. Http://ss64.com/nt/syntax-args.html

Крис Ноэ
источник
1
Интересный трюк с , setlocalно for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X)одно решением линии с forиспользоваться в качестве временного решения для %%~$PATH:Xтого , чтобы избежать callи %~$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
источник
3
Не будет работать, так как forнедостаточно умен, чтобы анализировать содержимое PATH. Например, он будет пропускать каталоги с пробелами. И даже при использовании for /fс delims=;ним он не будет работать правильно, если каталог содержит и заключен ;в кавычки.
Joey
@Joey, как насчет замены строки? Заменить ;с "; ": set quotedPath="%PATH:;="; "%".
XP1
1
XP1: Нет, все еще бесполезно. Попробуйте, добавив "C:\Folder with; semicolon, quoted"к пути, и посмотрите, что произойдет. По крайней мере, здесь он пытается рассматривать каждое «слово» отдельно, что в некотором смысле хуже, чем поведение раньше.
Joey
0

Иногда работает это простое решение, когда вы проверяете, соответствует ли результат ожидаемому. Первая строка выполняет команду и захватывает последнюю строку стандартного вывода.

FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.
бдомбро
источник
Но что, если системная среда использует другой язык?
Beachwalker
0

Если вы ищете что-то вроде меня в папке автозагрузки, следует перейти в папку. Например, я ищу exe в папке автозагрузки, и я использую этот код, например

@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!
)
Зафер АТЛИ
источник
Но это ищет program.exeне только в одной папке, но и в полном ПУТИ, если он существует,
jeb
-1

Используйте команду: powershell Test-Path "exe, который вы ищете"

Он вернет True, если присутствует, в противном случае - False.

Akkidukes
источник
Это не сработает. Test-Pathпроверяет только указанный путь, т.е. Test-Path nuget.exeвернет истину, только если nuget.exeнаходится в текущем каталоге. Если nuget.exe отсутствует в текущем каталоге, он вернет false, даже если он находится в каталоге, указанном в переменной PATH. В PowerShell Get-Commandможет работать лучше ( stackoverflow.com/questions/11242368/… ), но учтите, что для PowerShell текущий каталог находится не в пути.
Рональд Зариц
1
Как отметил @RonaldZarits, для полной поддержки PowerShell вы можете использовать Get-Command с двумя параметрами. Сначала укажите текущее местоположение каталога, а затем укажите только имя exe. (Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $nullвернет истину, если найден локально или в пути.
John C
-1

Для тех, кто ищет вариант PowerShell. Вы можете использовать Get-Commandкомандлет, передавая два элемента. Сначала укажите текущее местоположение .\каталога с префиксом, затем укажите только имя exe.

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

Это вернет истину, если будет найдено локальные или общесистемные пути.

Джон К
источник
Нет ничего лучше, чем голосовать против и запускать пользователей. Если вы не согласны и собираетесь пойти еще дальше, чтобы проголосовать против, то также добавьте комментарий, чтобы указать причину вашего несогласия, что это не лучший подход для получения желаемых результатов.
John C