68

如何检查 PATH 环境变量中是否已经存在目录?这是一个开始。不过,我对下面的代码所做的只是回显 %PATH% 中的第一个目录。由于这是一个 FOR 循环,您会认为它会枚举 %PATH% 中的所有目录,但它只获取第一个目录。

有没有更好的方法来做到这一点?在 %PATH% 变量上运行 find 或 findstr 之类的东西?我只想检查 %PATH% 中的目录列表中是否存在一个目录,以避免添加可能已经存在的内容。

FOR /F "delims=;" %%P IN ("%PATH%") DO (
    @ECHO %%~P
)
4

23 回答 23

103

首先,我将指出一些使这个问题难以完美解决的问题。然后我将介绍我能想到的最防弹的解决方案。

在本次讨论中,我将使用小写的路径来表示文件系统中的单个文件夹路径,并使用大写的 PATH 来表示 PATH 环境变量。

从实际的角度来看,大多数人想知道 PATH 是否包含给定路径的逻辑等价物,而不是 PATH 是否包含给定路径的精确字符串匹配。这可能是有问题的,因为:

  1. 路径中的尾随\是可选的
    大多数路径在有尾随和没有尾随的情况下都同样有效\。无论哪种方式,路径在逻辑上都指向相同的位置。PATH 经常混合有尾随和不带尾随的路径\。这可能是在 PATH 中搜索匹配项时最常见的实际问题。

    • 有一个例外:相对路径(指C盘当前工作目录)与(指C盘根目录 C:)有很大不同C:\

  2. 一些路径具有备用短名称
    任何不符合旧 8.3 标准的路径都有一个符合标准的备用短形式。这是我经常看到的另一个 PATH 问题,尤其是在商业环境中。

  3. Windows 接受/\作为路径中的文件夹分隔符。
    这种情况并不常见,但是可以使用/而不是指定路径,\并且它在 PATH 中(以及在许多其他 Windows 上下文中)可以正常工作

  4. Windows 将连续的文件夹分隔符视为一个逻辑分隔符。
    C:\FOLDER\\ 和 C:\FOLDER\ 是等价的。在处理路径时,这实际上在许多情况下都有帮助,因为开发人员通常可以附加\到路径而无需检查尾随是否\已经存在。但是,如果尝试执行精确的字符串匹配,这显然会导致问题。

    • 例外:不仅是C:,不同于C:\,而且C:\(有效路径),不同于C:\\(无效路径)。

  5. Windows 从文件和目录名称中修剪尾随的点和空格。
    "C:\test. "相当于"C:\test"

  6. 当前.\和父..\文件夹说明符可能出现在路径中不太可能在现实生活中
    看到,但类似于C:\.\parent\child\..\.\child\C:\parent\child

  7. 路径可以选择用双引号括起来。
    路径通常用引号括起来,以防止出现特殊字符,例如<space> , ; ^ & =. 实际上,任何数量的引号都可以出现在路径之前、之中和/或之后。除了防止特殊字符之外,它们被 Windows 忽略。除非路径包含 a ;,否则在 PATH 中永远不需要引号,但引号可能永远存在。

  8. 路径可以是完全限定的或相对的。
    完全限定路径指向文件系统中的一个特定位置。相对路径位置根据当前工作卷和目录的值而变化。相对路径有三种主要风格:

    • D:相对于卷 D 的当前工作目录:
    • \myPath是相对于当前工作量的(可以是 C:, D: 等)
    • myPath相对于当前工作卷和目录

    在 PATH 中包含相对路径是完全合法的。这在 Unix 世界中很常见,因为 Unix 默认不搜索当前目录,因此 Unix PATH 通常包含.\. 但是 Windows 默认会搜索当前目录,因此在 Windows PATH 中相对路径很少见。

因此,为了可靠地检查 PATH 是否已经包含路径,我们需要一种将任何给定路径转换为规范(标准)形式的方法。FOR 变量和参数扩展使用的~s修饰符是解决问题 1 - 6 和部分解决问题 7 的简单方法。~s修饰符删除封闭引号,但保留内部引号。问题 7 可以通过在比较之前从所有路径中显式删除引号来完全解决。请注意,如果路径实际上不存在,则~s修饰符不会将 附加\到路径,也不会将路径转换为有效的 8.3 格式。

问题~s在于它将相对路径转换为完全限定的路径。这对于问题 8 来说是有问题的,因为相对路径永远不应该与完全限定的路径匹配。我们可以使用 FINDSTR 正则表达式将路径分类为完全限定路径或相对路径。正常的完全限定路径必须以<letter>:<separator>but not开头<letter>:<separator><separator>,其中 <separator> 是\or /。UNC 路径始终是完全限定的,并且必须以\\. 在比较完全合格的路径时,我们使用~s修饰符。在比较相对路径时,我们使用原始字符串。最后,我们从不将完全限定路径与相对路径进行比较。此策略为问题 8 提供了一个很好的实用解决方案。唯一的限制是两个逻辑等效的相对路径可能被视为不匹配,但这是一个小问题,因为相对路径在 Windows PATH 中很少见。

还有一些额外的问题使这个问题复杂化:

9)处理包含特殊字符的 PATH 时,正常扩展不可靠。
特殊字符不需要在 PATH 中引用,但可以。所以像 PATH 一样 C:\THIS & THAT;"C:\& THE OTHER THING"是完全有效的,但它不能使用简单的扩展安全地扩展,因为两者"%PATH%"都会%PATH%失败。

10)路径定界符在路径名中也有效
A;用于在 PATH 中定界路径,但;也可以是路径中的有效字符,在这种情况下必须引用路径。这会导致解析问题。

jeb 在'Pretty print' windows %PATH% 变量中解决了问题 9 和 10 - 如何在 ';' 上拆分 在 CMD 外壳中

因此,我们可以将~s修饰符和路径分类技术与我对 jeb 的 PATH 解析器的变体结合起来,以获得这种几乎防弹的解决方案,用于检查给定路径是否已存在于 PATH 中。该函数可以在批处理文件中包含和调用,也可以独立运行并作为其自己的 inPath.bat 批处理文件调用。它看起来有很多代码,但其中一半以上是注释。

@echo off
:inPath pathVar
::
::  Tests if the path stored within variable pathVar exists within PATH.
::
::  The result is returned as the ERRORLEVEL:
::    0 if the pathVar path is found in PATH.
::    1 if the pathVar path is not found in PATH.
::    2 if pathVar is missing or undefined or if PATH is undefined.
::
::  If the pathVar path is fully qualified, then it is logically compared
::  to each fully qualified path within PATH. The path strings don't have
::  to match exactly, they just need to be logically equivalent.
::
::  If the pathVar path is relative, then it is strictly compared to each
::  relative path within PATH. Case differences and double quotes are
::  ignored, but otherwise the path strings must match exactly.
::
::------------------------------------------------------------------------
::
:: Error checking
if "%~1"=="" exit /b 2
if not defined %~1 exit /b 2
if not defined path exit /b 2
::
:: Prepare to safely parse PATH into individual paths
setlocal DisableDelayedExpansion
set "var=%path:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
set var=%var:""="%
set "var=%var:"=""Q%"
set "var=%var:;;="S"S%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
setlocal EnableDelayedExpansion
set "var=!var:"Q=!"
set "var=!var:"S"S=";"!"
::
:: Remove quotes from pathVar and abort if it becomes empty
set "new=!%~1:"=!"
if not defined new exit /b 2
::
:: Determine if pathVar is fully qualified
echo("!new!"|findstr /i /r /c:^"^^\"[a-zA-Z]:[\\/][^\\/]" ^
                           /c:^"^^\"[\\][\\]" >nul ^
  && set "abs=1" || set "abs=0"
::
:: For each path in PATH, check if path is fully qualified and then do
:: proper comparison with pathVar.
:: Exit with ERRORLEVEL 0 if a match is found.
:: Delayed expansion must be disabled when expanding FOR variables
:: just in case the value contains !
for %%A in ("!new!\") do for %%B in ("!var!") do (
  if "!!"=="" endlocal
  for %%C in ("%%~B\") do (
    echo(%%B|findstr /i /r /c:^"^^\"[a-zA-Z]:[\\/][^\\/]" ^
                           /c:^"^^\"[\\][\\]" >nul ^
      && (if %abs%==1 if /i "%%~sA"=="%%~sC" exit /b 0) ^
      || (if %abs%==0 if /i "%%~A"=="%%~C" exit /b 0)
  )
)
:: No match was found so exit with ERRORLEVEL 1
exit /b 1

该函数可以这样使用(假设批处理文件名为 inPath.bat):

set test=c:\mypath
call inPath test && (echo found) || (echo not found)



通常,检查路径是否存在于 PATH 中的原因是,如果路径不存在,则要附加该路径。这通常只需使用类似path %path%;%newPath%. 但是第 9 期证明了这是不可靠的。

另一个问题是如何在函数结束时通过 ENDLOCAL 屏障返回最终的 PATH 值,特别是如果可以在启用或禁用延迟扩展的情况下调用该函数。!如果启用延迟扩展,任何未转义的值都会损坏该值。

使用 jeb 在这里发明的惊人的安全返回技术解决了这些问题:http: //www.dostips.com/forum/viewtopic.php? p=6930#p6930

@echo off
:addPath pathVar /B
::
::  Safely appends the path contained within variable pathVar to the end
::  of PATH if and only if the path does not already exist within PATH.
::
::  If the case insensitive /B option is specified, then the path is
::  inserted into the front (Beginning) of PATH instead.
::
::  If the pathVar path is fully qualified, then it is logically compared
::  to each fully qualified path within PATH. The path strings are
::  considered a match if they are logically equivalent.
::
::  If the pathVar path is relative, then it is strictly compared to each
::  relative path within PATH. Case differences and double quotes are
::  ignored, but otherwise the path strings must match exactly.
::
::  Before appending the pathVar path, all double quotes are stripped, and
::  then the path is enclosed in double quotes if and only if the path
::  contains at least one semicolon.
::
::  addPath aborts with ERRORLEVEL 2 if pathVar is missing or undefined
::  or if PATH is undefined.
::
::------------------------------------------------------------------------
::
:: Error checking
if "%~1"=="" exit /b 2
if not defined %~1 exit /b 2
if not defined path exit /b 2
::
:: Determine if function was called while delayed expansion was enabled
setlocal
set "NotDelayed=!"
::
:: Prepare to safely parse PATH into individual paths
setlocal DisableDelayedExpansion
set "var=%path:"=""%"
set "var=%var:^=^^%"
set "var=%var:&=^&%"
set "var=%var:|=^|%"
set "var=%var:<=^<%"
set "var=%var:>=^>%"
set "var=%var:;=^;^;%"
set var=%var:""="%
set "var=%var:"=""Q%"
set "var=%var:;;="S"S%"
set "var=%var:^;^;=;%"
set "var=%var:""="%"
setlocal EnableDelayedExpansion
set "var=!var:"Q=!"
set "var=!var:"S"S=";"!"
::
:: Remove quotes from pathVar and abort if it becomes empty
set "new=!%~1:"^=!"
if not defined new exit /b 2
::
:: Determine if pathVar is fully qualified
echo("!new!"|findstr /i /r /c:^"^^\"[a-zA-Z]:[\\/][^\\/]" ^
                           /c:^"^^\"[\\][\\]" >nul ^
  && set "abs=1" || set "abs=0"
::
:: For each path in PATH, check if path is fully qualified and then
:: do proper comparison with pathVar. Exit if a match is found.
:: Delayed expansion must be disabled when expanding FOR variables
:: just in case the value contains !
for %%A in ("!new!\") do for %%B in ("!var!") do (
  if "!!"=="" setlocal disableDelayedExpansion
  for %%C in ("%%~B\") do (
    echo(%%B|findstr /i /r /c:^"^^\"[a-zA-Z]:[\\/][^\\/]" ^
                           /c:^"^^\"[\\][\\]" >nul ^
      && (if %abs%==1 if /i "%%~sA"=="%%~sC" exit /b 0) ^
      || (if %abs%==0 if /i %%A==%%C exit /b 0)
  )
)
::
:: Build the modified PATH, enclosing the added path in quotes
:: only if it contains ;
setlocal enableDelayedExpansion
if "!new:;=!" neq "!new!" set new="!new!"
if /i "%~2"=="/B" (set "rtn=!new!;!path!") else set "rtn=!path!;!new!"
::
:: rtn now contains the modified PATH. We need to safely pass the
:: value accross the ENDLOCAL barrier
::
:: Make rtn safe for assignment using normal expansion by replacing
:: % and " with not yet defined FOR variables
set "rtn=!rtn:%%=%%A!"
set "rtn=!rtn:"=%%B!"
::
:: Escape ^ and ! if function was called while delayed expansion was enabled.
:: The trailing ! in the second assignment is critical and must not be removed.
if not defined NotDelayed set "rtn=!rtn:^=^^^^!"
if not defined NotDelayed set "rtn=%rtn:!=^^^!%" !
::
:: Pass the rtn value accross the ENDLOCAL barrier using FOR variables to
:: restore the % and " characters. Again the trailing ! is critical.
for /f "usebackq tokens=1,2" %%A in ('%%^ ^"') do (
  endlocal & endlocal & endlocal & endlocal & endlocal
  set "path=%rtn%" !
)
exit /b 0
于 2011-11-08T05:54:11.633 回答
40

我有一段时间没有进行任何批处理文件编程,但是:

echo ;%PATH%; | find /C /I ";<string>;"

如果找不到字符串,应该给你 0,如果是,应该给你 1 或更多。

编辑:添加了不区分大小写的标志,感谢 Panos。

于 2008-09-26T19:19:31.737 回答
23

检查路径中是否存在某些内容的另一种方法是执行一些无辜的可执行文件,如果它存在则不会失败,并检查结果。例如,下一个代码片段检查maven是否在路径中:

mvn --help > NUL 2> NUL 
if errorlevel 1 goto mvnNotInPath

所以我尝试运行mvn --help,忽略输出(如果 maven 存在,实际上不想看到帮助)(> NUL),如果找不到 maven 也不显示错误消息(2>无)。

于 2010-04-01T09:24:15.493 回答
12

在阅读了这里的答案后,我想我可以提供一个新的观点:如果这个问题的目的是知道某个可执行文件的路径是否存在%PATH%,如果不存在,则插入它(这是唯一的理由我认为),那么它可能会以稍微不同的方式解决:“如何检查某个可执行程序的目录是否存在于 %PATH% 中”?这个问题可以通过这种方式轻松解决:

for %%p in (programname.exe) do set "progpath=%%~$PATH:p"
if not defined progpath (
   rem The path to programname.exe don't exist in PATH variable, insert it:
   set "PATH=%PATH%;C:\path\to\progranname"
)

如果您不知道可执行文件的扩展名,只需查看所有文件:

set "progpath="
for %%e in (%PATHEXT%) do (
   if not defined progpath (
      for %%p in (programname.%%e) do set "progpath=%%~$PATH:p"
   )
)
于 2013-10-28T19:06:25.383 回答
6

使用forand delims,您无法捕获任意数量的字段(正如Adam 指出的那样),因此您必须使用循环技术。以下命令脚本将在PATH单独的行上列出环境变量中的每个路径:

@echo off 
setlocal 
if "%~1"=="" (
    set PATHQ=%PATH%
) else (
    set PATHQ=%~1 ) 
:WHILE
    if "%PATHQ%"=="" goto WEND
    for /F "delims=;" %%i in ("%PATHQ%") do echo %%i
    for /F "delims=; tokens=1,*" %%i in ("%PATHQ%") do set PATHQ=%%j
    goto WHILE 
:WEND

它模拟了许多编程语言中的经典while …<em>wend 构造。有了这个,你可以使用类似的东西findstr来过滤和寻找特定的路径。例如,如果您将上述脚本保存在一个名为tidypath.cmdthen 的文件中,那么您可以通过管道传输到findstr,在标准程序目录下查找路径(使用不区分大小写的匹配):

> tidypath | findstr /i "%ProgramFiles%"
于 2008-10-01T14:04:07.193 回答
4

这将寻找一个精确但不区分大小写的匹配,因此请注意任何尾随反斜杠等:

for %P in ("%path:;=";"%") do @if /i %P=="PATH_TO_CHECK" echo %P exists in PATH

或者,在一个带有参数的批处理文件(例如 checkpath.bat)中:

@for %%P in ("%path:;=";"%") do @if /i %%P=="%~1" echo %%P exists in PATH

在后一种形式中,可以调用 egcheckpath "%ProgramFiles%"来查看指定的路径是否已经存在于 PATH 中。

请注意,此实现假定单个路径项中不存在分号或引号。

于 2011-04-06T21:10:29.877 回答
3

只是为了详细说明Heyvoon (2015.06.08)使用 Powershell 的响应,这个简单的 Powershell 脚本应该为您提供有关 %path% 的详细信息

$env:Path -split ";" | % {"$(test-path $_);$_"}

生成这种您可以独立验证的输出

True;C:\WINDOWS
True;C:\WINDOWS\system32
True;C:\WINDOWS\System32\Wbem
False;C:windows\System32\windowsPowerShell\v1.0\
False;C:\Program Files (x86)\Java\jre7\bin

重新组装以更新路径:

$x=$null;foreach ($t in ($env:Path -split ";") ) {if (test-path $t) {$x+=$t+";"}};$x
于 2017-05-05T23:51:57.040 回答
2

您还可以使用子字符串替换来测试是否存在子字符串。在这里,我删除引号以创建 PATH_NQ,然后从 PATH_NQ 中删除“c:\mydir”并将其与原始文件进行比较以查看是否有任何更改:

set PATH_NQ=%PATH:"=%
if not "%PATH_NQ%"=="%PATH_NQ:c:\mydir=%" goto already_in_path
set PATH=%PATH%;c:\mydir
:already_in_path
于 2011-07-23T18:40:48.823 回答
2

如果您的问题是“为什么这个 cmd 脚本片段不起作用?” 那么答案是for /f遍历行。分割线成字段,delims但您只捕获%%P. 没有办法通过for /f循环捕获任意数量的字段。

于 2008-09-26T22:36:27.037 回答
2

我使用for循环实现了您的实现,并将其扩展为迭代路径的所有元素的东西。for 循环的每次迭代都会从整个路径(保存在 %q 和 %r 中)中删除路径的第一个元素 (%p)。

@echo off
SET MYPATHCOPY=%PATH%

:search
for /f "delims=; tokens=1,2*" %%p in ("%MYPATHCOPY%") do (
   @echo %%~p
   SET MYPATHCOPY=%%~q;%%~r
)

if "%MYPATHCOPY%"==";" goto done;
goto search;

:done

样本输出:

Z:\>path.bat
C:\Program Files\Microsoft DirectX SDK (November 2007)\Utilities\Bin\x86
c:\program files\imagemagick-6.3.4-q16
C:\WINDOWS\system32
C:\WINDOWS
C:\SFU\common\
c:\Program Files\Debugging Tools for Windows
C:\Program Files\Nmap
于 2008-09-27T00:26:10.097 回答
2

我结合了上面的一些答案来提出这个问题,以确保给定的路径条目与给定 的一样存在,并且尽可能简洁,并且在命令行上没有垃圾回声。

set myPath=<pathToEnsure | %1>
echo ;%PATH%; | find /C /I ";%myPath%;" >nul
if %ERRORLEVEL% NEQ 0 set PATH=%PATH%;%myPath%
于 2011-10-11T19:44:38.757 回答
1

一般来说,这是在路径上放置一个 exe/dll。只要此文件不会出现在其他任何地方:

@echo off
where /q <put filename here>    
if %errorlevel% == 1 (
    setx PATH "%PATH%;<additional path stuff>"
) else (
    echo "already set path"
)
于 2012-06-13T15:37:09.630 回答
1

这是 Kevin Edwards 使用字符串替换的答案的变体。基本模式是:

IF "%PATH:new_path=%" == "%PATH%" PATH=%PATH%;new_path

例如:

IF "%PATH:C:\Scripts=%" == "%PATH%" PATH=%PATH%;C:\Scripts

简而言之,我们进行条件测试,尝试new_pathPATH环境变量中删除/替换。如果new_path不存在,则条件成功,并且new_pathPATH第一次附加到。如果new_path已经存在,则条件失败,我们不会添加new_path第二次。

于 2014-04-28T23:58:52.153 回答
1

您提到如果目录已经存在,您希望避免将目录添加到搜索路径中。您打算将目录永久存储到路径中,还是只是为了批处理文件而暂时存储?

如果您希望将目录永久添加(或删除)到 PATH,请查看用于管理任务的 Windows 资源工具包工具中的路径管理器 (pathman.exe) 实用程序,http://support.microsoft.com/kb/927229。有了它,您可以添加或删除系统和用户路径的组件,它将处理异常,例如重复条目。

如果您只需要临时修改批处理文件的路径,我只会在路径前面添加额外的路径,由于路径中的重复条目,存在轻微性能损失的风险。

于 2008-10-01T13:43:24.983 回答
1

基于 rcar 的答案,您必须确保未找到目标的子字符串。

if a%X%==a%PATH% echo %X% is in PATH
echo %PATH% | find /c /i ";%X%"
if errorlevel 1 echo %X% is in PATH
echo %PATH% | find /c /i "%X%;"
if errorlevel 1 echo %X% is in PATH
于 2008-09-26T22:44:26.613 回答
1

作为替代方案:

  1. 在您将要搜索PATH变量的文件夹中,创建一个临时文件,其名称如此不寻常,您永远不会期望计算机上的任何其他文件都有。

  2. 使用标准的批处理脚本构造,该构造允许您通过查找由某个环境变量(通常为PATH)定义的目录列表来执行文件搜索。

  3. 检查搜索结果是否与相关路径匹配,并显示结果。

  4. 删除临时文件。

这可能看起来像这样:

@ECHO OFF
SET "mypath=D:\the\searched-for\path"
SET unusualname=nowthisissupposedtobesomeveryunusualfilename
ECHO.>"%mypath%\%unusualname%"
FOR %%f IN (%unusualname%) DO SET "foundpath=%%~dp$PATH:f"
ERASE "%mypath%\%unusualname%"
IF "%mypath%" == "%foundpath%" (
  ECHO The dir exists in PATH
) ELSE (
  ECHO The dir DOES NOT exist in PATH
)

已知的问题:

  1. 该方法仅在目录存在时才有效(并非总是如此)。

  2. 在目录中创建/删除文件会影响其“修改日期/时间”属性(有时这可能是不良影响)。

  3. 在一个人的脑海中编造一个全球唯一的文件名并不能被认为是非常可靠的。生成这样的名称本身并不是一项简单的任务。

于 2011-04-06T22:59:52.650 回答
1

这个版本运行得相当好。它只是检查 vim71 是否在路径中,如果没有,则将其添加到前面。

@echo off
echo %PATH% | find /c /i "vim71" > nul
if not errorlevel 1 goto jump
PATH = C:\Program Files\Vim\vim71\;%PATH%
:jump

这个demo是为了说明errorlevel的逻辑:

@echo on
echo %PATH% | find /c /i "Windows"
if "%errorlevel%"=="0" echo Found Windows
echo %PATH% | find /c /i "Nonesuch"
if "%errorlevel%"=="0" echo Found Nonesuch

vim71 代码中的逻辑是相反的,因为 errorlevel 1 等价于 errorlevel >= 1。因此 errorlevel 0 将始终评估为真,因此not errorlevel 1使用“”。

如果您使用 setlocal 和 endlocal 来本地化您的环境设置,则可能不需要后记检查,例如

@echo off
setlocal
PATH = C:\Program Files\Vim\vim71\;%PATH%
rem your code here
endlocal

在 endlocal 之后,您将返回原始路径。

于 2011-10-07T09:15:02.270 回答
1

如果目录不存在,则将目录添加到 PATH:

set myPath=c:\mypath
For /F "Delims=" %%I In ('echo %PATH% ^| find /C /I "%myPath%"') Do set pathExists=%%I 2>Nul
If %pathExists%==0 (set PATH=%myPath%;%PATH%)
于 2011-03-14T09:23:23.083 回答
1

对“addPath”脚本的注释;当提供带有空格的路径时,它会抛出。

示例:调用 addPath "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin"

产生:“文件”不是内部或外部命令、可运行程序或批处理文件。

于 2011-12-14T09:51:33.503 回答
1

您可以使用 PoweShell 完成此操作;

Test-Path $ENV:SystemRoot\YourDirectory
Test-Path C:\Windows\YourDirectory

这返回TRUEFALSE

简短、简单、容易!

于 2015-06-08T14:06:01.887 回答
0

此例程将在路径变量中搜索 path\ 或 file.ext,如果找到则返回 0。如果引用,路径\ 或文件可能包含空格。如果一个变量作为最后一个参数传递,它将被设置为d:\path\file.

@echo off&goto :PathCheck
:PathCheck.CMD
echo.PathCheck.CMD: Checks for existence of a path or file in %%PATH%% variable
echo.Usage: PathCheck.CMD [Checkpath] or [Checkfile] [PathVar]
echo.Checkpath must have a trailing \ but checkfile must not
echo.If Checkpath contains spaces use quotes ie. "C:\Check path\"
echo.Checkfile must not include a path, just the filename.ext
echo.If Checkfile contains spaces use quotes ie. "Check File.ext"
echo.Returns 0 if found, 1 if not or -1 if checkpath does not exist at all
echo.If PathVar is not in command line it will be echoed with surrounding quotes
echo.If PathVar is passed it will be set to d:\path\checkfile with no trailing \
echo.Then %%PathVar%% will be set to the fully qualified path to Checkfile
echo.Note: %%PathVar%% variable set will not be surrounded with quotes
echo.To view the path listing line by line use: PathCheck.CMD /L
exit/b 1

:PathCheck
if "%~1"=="" goto :PathCheck.CMD
setlocal EnableDelayedExpansion
set "PathVar=%~2"
set "pth="
set "pcheck=%~1"
if "%pcheck:~-1%" equ "\" (
  if not exist %pcheck% endlocal&exit/b -1
  set/a pth=1
) 
for %%G in ("%path:;=" "%") do (
  set "Pathfd=%%~G\"
  set "Pathfd=!Pathfd:\\=\!"
  if /i "%pcheck%" equ "/L" echo.!Pathfd!
  if defined pth (
    if /i "%pcheck%" equ "!Pathfd!" endlocal&exit/b 0
  ) else (
    if exist "!Pathfd!%pcheck%" goto :CheckfileFound
  )
)
endlocal&exit/b 1

:CheckfileFound
endlocal&(
  if not "%PathVar%"=="" (
    call set "%~2=%Pathfd%%pcheck%"
  ) else (echo."%Pathfd%%pcheck%")
  exit/b 0
)
于 2012-10-14T17:07:19.937 回答
0
rem https://stackoverflow.com/a/59571160/2292993
rem Don't get mess with %PATH%, it is a concatenation of USER+SYSTEM, and will cause a lot of duplication in the result. 
for /f "usebackq tokens=2,*" %%A in (`reg query HKCU\Environment /v PATH`) do set userPATH=%%B
rem userPATH should be %USERPROFILE%\AppData\Local\Microsoft\WindowsApps

rem https://stackoverflow.com/questions/141344
for /f "delims=" %%A in ('echo ";%userPATH%;" ^| find /C /I ";%WINAPPS%;"') do set pathExists=%%A
If %pathExists%==0 (
    echo Inserting user path...
    setx PATH "%WINAPPS%; %userPATH%"
)
于 2022-01-07T06:44:29.283 回答
0

-contains为我工作

$pathToCheck = "c:\some path\to\a\file.txt"

$env:Path - split ';' -contains $pathToCheck

在路径不存在时添加路径我使用

$pathToCheck = "c:\some path\to\a\file.txt"

if(!($env:Path -split ';' -contains $vboxPath)) {
  $documentsDir = [Environment]::GetFolderPath("MyDocuments")
  $profileFilePath = Join-Path $documentsDir "WindowsPowerShell/profile.ps1"
  Out-File -FilePath $profileFilePath -Append -Force -Encoding ascii -InputObject "`$env:Path += `";$pathToCheck`""
  Invoke-Expression -command $profileFilePath
}
于 2019-07-04T08:03:31.233 回答