如何在批处理脚本中查找应用程序的完整路径

19

如果已经安装了应用程序XYZ,我该如何在批处理脚本中找到其完整路径?

说明:

  1. 该应用程序不在系统的PATH环境变量中
  2. 我只知道它的名称,如此例中的"ISTool.exe",我想得到C:\Program\ISTool\ISTool.exe这个路径

请问您能否澄清一下您的任务?您是想要通过输入“iTunes”来获取“C:\Program Files\iTunes”这个路径吗? - Helen
所以,你想输入“ISTool.exe”,但它不在路径中?你需要搜索整个驱动器。-- dir c:\ISTool.exe /s /b -- 你可以将输出导向任何地方,但如果文件出现多次,你就需要处理多行 -- 此外,如果用户有多个驱动器,你可能需要扫描所有驱动器(不确定获取所有驱动器的最佳方法是什么,也许是非可移动驱动器的 WMI 查询...)-- 但这可能需要很长时间,即使使用 SSD -- 最好扫描 5 或 6 个已知位置,包括 %ProgramFiles%\ISTool\ 和 %ProgramFiles(x86)%\ISTool 等。 - BrainSlugs83
6个回答

32
您可以在路径上(或其他类似路径的字符串上)找到可执行文件:
c:\> for %i in (cmd.exe) do @echo. %~$PATH:i
C:\WINDOWS\system32\cmd.exe

c:\> for %i in (python.exe) do @echo. %~$PATH:i
C:\Python25\python.exe

细节内容可以在"for /?"命令的帮助文本结尾处找到,此处提供简要摘要:

%~i    - expands %i removing any surrounding quotes.
%~fi   - expands %i to a fully qualified path name.
%~di   - expands %i to a drive letter only.
%~pi   - expands %i to a path only.
%~ni   - expands %i to a file name only.
%~xi   - expands %i to a file extension only.
%~si   - expanded path contains short names only.
%~ai   - expands %i to file attributes of file.
%~ti   - expands %i to date/time of file.
%~zi   - expands %i to size of file.
%~$P:i - searches the directories listed in the P environment variable
         and expands %i to the fully qualified name of the first one found.
         If the environment variable name is not defined or the file is not
         found by the search, then this modifier expands to the empty string.

修饰符可以组合使用以获得复合结果:

%~dpi    - expands %i to a drive letter and path only.
%~nxi    - expands %i to a file name and extension only.
%~fsi    - expands %i to a full path name with short names only.
%~dp$P:i - searches the directories listed in the P environment variable
           for %i and expands to the drive letter and path of the first
           one found.
%~ftzai  - expands %i to a DIR like output line.

如果您的可执行文件不在路径上(根据您的编辑),您最好使用dir的裸/子目录格式,该格式将为您完成此操作。从根目录开始:

dir /b /s ISTool.exe

使用 dir /b /s 命令将获取该驱动器上所有具有该名称的文件。然后,您只需要解析输出即可。我个人更喜欢使用 Cygwin 的 "find /cygdrive -name ISTool.exe",但这是因为我已经安装了它。您可能不想要那个(甚至没有那个选项)。

更新:

dir /b /s 命令会花费一段时间,因为它基本上是在搜索整个磁盘。如果这是一个问题,您可以考虑定期创建所有磁盘上所有文件的缓存记录,方法是使用类似以下命令的 cmd 文件:

@echo off
setlocal enableextensions enabledelayedexpansion
del c:\files.cache.tmp >nul: 2>nul:
for %%d in (c d e) do (
    cd /d %%d:\
    dir /b /s >>c:\files.cache.tmp
)
del c:\files.cache >nul: 2>nul:
move c:\files.cache.tmp c:\files.cache
endlocal
您可以使用定时任务来实现这一点,无论是每晚(对于始终运行的服务器)还是开机启动(对于桌面电脑)。您甚至可以使脚本更加智能,只在每隔几天才运行一次(我有一个自动备份脚本,在我支持的家用机器上执行类似的操作)。这将在临时缓存文件中创建列表,然后覆盖原始文件,以确保文件不存在的时间最短。

然后,您只需使用:

findstr \\ISTool.exe c:\files.cache

查找你的所有文件。


啊,但它不在路径中。我会编辑问题以使其更清晰明了。 - Nifle
dir /b /s ISTool.exe 可以工作,但是需要很长时间,这是不可接受的。在我的电脑上,它花费了43秒钟。 - Nifle
你有考虑升级吗?开个玩笑,但是它必须搜索整个磁盘,所以需要一些时间。你会经常做这种事情吗?如果是的话,你可能想考虑缓存这些信息的想法,可以看看我的更新。 - paxdiablo

9

根据这里真正有用的答案,我编写了以下两个批处理文件,并想在这里分享(我知道这个帖子现在已经有3年了,但是当你搜索时它会作为第一个匹配项...):

1)which.bat:

@echo off
REM emulate the Linux which command
if "%1" == "" (
  echo Usage: %~nx0 ^<command[.ext]^>
  exit /b
)
setlocal
for %%P in (%PATHEXT%) do (
  for %%I in (%1 %1%%P) do (
    if exist "%%~$PATH:I" (
      echo %%~$PATH:I
      exit /b
    )
  )
)

虽然不完美,因为总是有两个测试,但速度足够快,所以我没有进一步的烦恼;当然,也可以先单独测试%1 ...

2) findfile.bat:

@echo off
REM emulate the Linux find command
if "%1" == "" (
  echo Usage: %~nx0 ^<startdir^> ^<file^>
  exit /b
)
setlocal
for /f "delims=" %%A in ('dir /b /s %1\%2') do set F=%%A
if exist "%F%" echo %F%

3
这是我得到的最接近的结果。一个缺点是它只能在每次执行时针对一个驱动器工作,但这可以使其更加灵活。另一个问题是输出,它始终在路径和文件名之间包含一个//。但根据定义,这是一个有效的路径。
@ECHO OFF

SET filename=autoexec.bat

FOR /R C:\ %%a IN (\) DO (
   IF EXIST "%%a\%filename%" (

      SET fullpath=%%a%filename%
      GOTO break
   )
)
:break

ECHO %fullpath%

将会交付:C:\\autoexec.bat

编辑:

为了解释,for循环迭代从给定路径(C:\)开始的所有目录,并检查该目录中是否存在文件名。如果存在,则将两个变量连接并存储在%fullpath%中,并通过跳转终止循环。


谢谢!我需要从"%UserProfile%\.nuget\packages\OpenCover""%UserProfile%\.nuget\packages\ReportGenerator"中找到tools\OpenCover.Console.exetools/net47/ReportGenerator.exe,这个脚本很有帮助。 - Yijun Blue Yuan

0

或者,像EverythingUltraSearch(免费软件)、SwiftSearch这样的程序可以搜索MFT(NTFS分区的)文件(因此可以非常快速地进行搜索),但维基百科声称这种方法可能会通过查找不应该找到的内容来破坏您的安全模型。其中一些看起来像是有一些命令行参数,我没有使用过它们,但如果您要进行全盘搜索,也许它们会有所帮助。


0
有时候这个简单的解决方案很有效,你可以检查输出是否符合预期。第一行运行命令并获取标准输出的最后一行。
FOR /F "tokens=*" %%i in (' "xcopy /? 2> nul" ') do SET xcopyoutput=%%i
if "%xcopyoutput%"=="" echo xcopy not in path.

0

我从其他人那里得到的答案虽然有效(但速度慢或使用了额外的文件),并且适用于任何exe,但并不真正符合我的需求。

因为我想要找到一个特定的exe,所以我使用REG QUERY在注册表中查找。我找到了一个包含我想要查找的数据的键,并提取了它。

结果很快,代码行数很少,但不是很美观也不可重复使用。

简短的例子:

@ECHO off
SETLOCAL
set found=
FOR /F "tokens=1-3 delims= " %%a IN ('REG QUERY "HKEY_CLASSES_ROOT\Applications\ISTool.exe\shell\OpenWithISTool\command"') DO (
 set found=%%c
)

for /f "tokens=1-2" %%a in ("%found%") do (
 set my_exe=%%a
)
echo %my_exe%
ENDLOCAL

这将导致 "C:\Program\ISTool\ISTool.exe"(带引号)
注意:上面的 delims= 后面跟着一个制表符


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接