【问题标题】:How to test if an executable exists in the %PATH% from a windows batch file?如何测试 Windows 批处理文件中的 %PATH% 中是否存在可执行文件?
【发布时间】:2011-06-14 11:37:25
【问题描述】:

我正在寻找一种简单的方法来测试 Windows 批处理文件中的 PATH 环境变量中是否存在可执行文件。

不允许使用非操作系统提供的外部工具。所需的最低 Windows 版本是 Windows XP。

【问题讨论】:

标签: windows batch-file batch-processing


【解决方案1】:

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

【讨论】:

  • 非常好和简单!谢谢!
【解决方案2】:
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) 文件中解析和在命令行上的解析不同(因为批处理文件有 %0%9),因此您必须在此处将 % 加倍。在命令行上这不是必需的,所以变量只是%X

【讨论】:

  • 我喜欢你的方法,但如果你能提供完整版本会更好,它也使用 PATHEXT。
  • 对于 XP,您需要循环脚本(或从 RK 下载 where.exe)。 Vista 和 7 附带 where.exe。我知道 OP 专门说 XP,但对于后代来说,最好的答案总是使用 where myExecutable
  • 瑞恩:嗯?我想我无法解析你的句子。
  • 我是批处理脚本初学者,我不确定 %%x 是什么意思。在我的 Windows 7 系统上,我尝试输入: for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X) 然后点击返回。我得到这个回应:C:\Users\James>for %%X in (cmd.exe) do (set FOUND=%%~$PATH:X) %%X 在这个时候是意外的。
  • simengineer:在批处理文件中的解析和在命令行上的解析不同(因为批处理文件有%0%9),所以你必须把%加倍。在命令行上这不是必需的,所以for 变量只是%x
【解决方案3】:

这是一个简单的解决方案,它尝试运行应用程序并在之后处理任何错误

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

错误代码 9009 通常表示找不到文件。

唯一的缺点是file.exe 如果找到就会实际执行(在某些情况下这是不可取的)。

【讨论】:

  • 唯一的缺点是“file.exe”被执行(在某些情况下是不需要的)
【解决方案4】:

这可以通过参数替换来完成。

%~$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

【讨论】:

  • setlocal 的有趣技巧,但for %%X in (myExecutable.exe) do (set FOUND=%%~$PATH:X) 是一种解决方案,for 用作%%~$PATH:X 的解决方法,以避免call%~$PATH:1
【解决方案5】:

对于那些寻找 PowerShell 选项的人。您可以使用Get-Command cmdlet 传递两个项目。首先给出以.\ 为前缀的当前目录位置,然后只给出exe 名称。

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

如果在本地或系统范围的路径中找到,则返回 true。

【讨论】:

  • 没有什么比投票和运行用户更好的了。如果您不同意并且打算投反对票,那么还要添加评论,说明您不同意这不是获得预期结果的好方法的原因。
【解决方案6】:
@echo off
set found=
set prog=cmd.exe
for %%i in (%path%) do if exist %%i\%prog% set found=%%i
echo "%found%"
if "%found%"=="" ....

【讨论】:

  • 无法工作,因为 for 不够聪明,无法解析 PATH 的内容。例如,它将丢失带有空格的目录。即使您将for /fdelims=; 一起使用,如果目录包含; 并被引用,它也将无法正常工作。
  • @Joey,字符串替换怎么样?将; 替换为"; "set quotedPath="%PATH:;="; "%"
  • XP1:不,仍然没用。通过将"C:\Folder with; semicolon, quoted" 附加到路径来尝试一下,看看会发生什么。至少在这里它尝试单独处理每个»word«,在某种程度上,这比以前的行为更糟​​糕。
【解决方案7】:

有时这种简单的解决方案会起作用,您可以在其中检查输出是否符合您的预期。第一行运行命令并获取标准输出的最后一行。

FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.

【讨论】:

  • 但是如果系统环境使用其他语言呢?
【解决方案8】:

使用命令:powershell Test-Path "你要找的exe"

如果存在则返回 True,否则返回 False。

【讨论】:

  • 这行不通。 Test-Path 只检查指定的路径,即 Test-Path nuget.exe 只有当 nuget.exe 在当前目录中时才会返回 true。如果 nuget.exe 不在当前目录中,它将返回 false,即使它位于 PATH 变量中列出的目录中。在 PowerShell 中 Get-Command 可能会更好(stackoverflow.com/questions/11242368/…),但要考虑到对于 PowerShell,当前目录不在路径中。
  • 正如@RonaldZarits 所指出的,要获得完整的 PowerShell 支持,您可以使用带有两个选项的 Get-Command。首先给出当前目录位置,然后只给出 exe 名称。如果在本地或路径中找到(Get-Command ".\notepad", "notepad" -ErrorAction Ignore -CommandType Application) -ne $null,将返回 true。
猜你喜欢
  • 1970-01-01
  • 2010-12-12
  • 2010-09-27
  • 2012-07-28
  • 2017-09-10
  • 1970-01-01
  • 1970-01-01
  • 2011-03-02
相关资源
最近更新 更多