Как проверить, существует ли каталог в%PATH%?

Как проверить, существует ли каталог в переменной среды PATH? Вот начало. Все, что мне удалось сделать с помощью приведенного ниже кода, - это отобразить первый каталог в% PATH%. Поскольку это цикл FOR, можно подумать, что он перечислит все каталоги в% PATH%, но он получит только первый.

Есть ли лучший способ сделать это? Что-то вроде find или findstr, работающего с переменной% PATH%? Я просто хотел бы проверить, существует ли каталог в списке каталогов в% PATH%, чтобы избежать добавления чего-то, что уже может быть там.

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

23 ответа

Сначала я укажу на ряд проблем, которые затрудняют решение этой проблемы. Затем я представлю самое пуленепробиваемое решение, которое мне удалось найти.

Для этого обсуждения я буду использовать путь в нижнем регистре для представления одного пути к папке в файловой системе, а путь в верхнем регистре для представления переменной среды PATH.

С практической точки зрения, большинство людей хотят знать, содержит ли PATH логический эквивалент заданного пути, а не содержит ли PATH точное совпадение строки заданного пути. Это может быть проблематично, потому что:

  1. Трейлинг \ необязательно в пути
    Большинство путей одинаково хорошо работают как с трейлингом, так и без него. \, Путь логически указывает на одно и то же место в любом случае. ПУТЬ часто имеет смесь путей как с трейлингом, так и без него. \, Это, вероятно, самая распространенная практическая проблема при поиске совпадения в 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, за исключением защиты от специальных символов. Кавычки никогда не требуются в PATH, если путь не содержит ;, но кавычки могут присутствовать, тем не менее.

  8. Путь может быть полностью определенным или относительным.
    Полный путь указывает на одно конкретное место в файловой системе. Относительное расположение пути изменяется в зависимости от значения текущих рабочих томов и каталогов. Существует три основных варианта относительных путей:

    • D: Относительно текущего рабочего каталога тома D:
    • \myPath относительно текущего рабочего объема (может быть C:, D: и т. д.)
    • myPath относительно текущего рабочего объема и каталога

    Вполне законно включать относительный путь в PATH. Это очень часто встречается в мире Unix, потому что Unix не ищет текущий каталог по умолчанию, поэтому PATH Unix часто будет содержать .\, Но Windows выполняет поиск в текущем каталоге по умолчанию, поэтому относительные пути редко встречаются в Windows PATH.

Таким образом, чтобы надежно проверить, содержит ли PATH путь, нам нужен способ преобразовать любой данный путь в каноническую (стандартную) форму. ~s Модификатор, используемый для расширения переменных и аргументов FOR, является простым методом, который решает проблемы 1 - 6 и частично решает проблему 7. ~s Модификатор удаляет заключающие в кавычки, но сохраняет внутренние кавычки. Проблема 7 может быть полностью решена путем явного удаления кавычек из всех путей перед сравнением. Обратите внимание, что если путь не существует физически, то ~s Модификатор не будет добавлять \ к пути, и при этом это не будет преобразовывать путь в действительный формат 8.3.

Проблема с ~s это преобразует относительные пути в полностью определенные пути. Это проблематично для проблемы 8, потому что относительный путь никогда не должен соответствовать полностью определенному пути. Мы можем использовать регулярные выражения FINDSTR для классификации пути как полностью определенного или относительного. Нормальный полный путь должен начинаться с <letter>:<separator> но нет <letter>:<separator><separator> где <разделитель> либо \ или же /, UNC-пути всегда полностью определены и должны начинаться с \\, При сравнении полностью определенных путей мы используем ~s модификатор. При сравнении относительных путей мы используем необработанные строки. Наконец, мы никогда не сравниваем полностью определенный путь с относительным путем. Эта стратегия обеспечивает хорошее практическое решение для проблемы 8. Единственное ограничение - два логически эквивалентных относительных пути могут рассматриваться как несоответствующие, но это незначительная проблема, потому что относительные пути встречаются редко в Windows PATH.

Есть некоторые дополнительные проблемы, которые усложняют эту проблему:

9) Нормальное расширение не является надежным при работе с PATH, который содержит специальные символы.
Специальные символы не нужно заключать в кавычки, но они могут быть. Так что ПУТЬ как C:\THIS & THAT;"C:\& THE OTHER THING" вполне допустимо, но не может быть безопасно расширено с помощью простого расширения, потому что оба "%PATH%" а также %PATH% не удастся.

10) Разделитель пути также допустим в имени пути
; используется для разграничения путей внутри PATH, но ; также может быть допустимым символом в пути, и в этом случае путь должен быть заключен в кавычки. Это вызывает проблему разбора.

Джеб решил обе проблемы 9 и 10 в переменной "Pretty print" Windows %PATH% - как разделить на ";" в оболочке CMD

Таким образом, мы можем объединить ~s методы модификатора и классификации путей, а также мой вариант синтаксического анализатора PATH от jeb, чтобы получить это почти пуленепробиваемое решение для проверки, существует ли заданный путь в 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 демонстрирует, как это ненадежно.

Другая проблема заключается в том, как вернуть окончательное значение PATH через барьер ENDLOCAL в конце функции, особенно если функцию можно вызывать с включенным или отключенным отложенным расширением. Любой ушел ! повредит значение, если включено отложенное расширение.

Эти проблемы решаются с использованием удивительной техники безопасного возврата, которую Джеб изобрел здесь: http://www.dostips.com/forum/viewtopic.php?p=6930

@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

Я давно не занимался программированием пакетных файлов, но:

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

должен дать вам 0, если строка не найдена, и 1 или более, если она есть.

РЕДАКТИРОВАТЬ: Добавлен флаг без учета регистра, благодаря Panos.

Другой способ проверить, находится ли что-то в пути, состоит в том, чтобы выполнить невинный исполняемый файл, который не потерпит неудачу, если он там находится, и проверить результат. Например, следующий фрагмент кода проверяет, находится ли maven в пути:

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

Поэтому я пытаюсь запустить mvn --help, игнорировать вывод (на самом деле не хочу видеть справку, если есть maven)( > NUL), а также не отображать сообщение об ошибке, если maven не был найден (2> NUL).

Прочитав ответы здесь, я думаю, что могу представить новую точку зрения: если целью этого вопроса является узнать, существует ли путь к определенному исполняемому файлу в %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"
   )
)

С помощью for а также delims вы не можете захватить произвольное количество полей (как указал Адам), поэтому вместо этого вы должны использовать технику зацикливания. Следующий командный скрипт перечислит каждый путь в 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... wend, встречающуюся во многих языках программирования. С этим на месте, вы можете использовать что-то вроде findstr чтобы впоследствии фильтровать и искать конкретный путь. Например, если вы сохранили вышеуказанный скрипт в файле с именем tidypath.cmd тогда вот как вы могли бы findstr, ища пути в стандартном каталоге программ (используя регистронезависимое соответствие):

> tidypath | findstr /i "%ProgramFiles%"

Просто для того, чтобы уточнить ответ 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

пересобрать для обновления Path:

$x=$null;foreach ($t in ($env:Path -split ";") ) {if (test-path $t) {$x+=$t+";"}};$x

Это будет искать точное, но нечувствительное к регистру совпадение, так что не забывайте о конце и т.д.

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

В последней форме можно назвать, например, checkpath "%ProgramFiles%" чтобы увидеть, существует ли указанный путь в PATH.

Обратите внимание, что эта реализация предполагает отсутствие точек с запятой или кавычек внутри одного элемента пути.

Вы также можете использовать замену подстроки, чтобы проверить наличие подстроки. Здесь я удаляю кавычки для создания PATH_NQ, затем я удаляю "c:\mydir" из PATH_NQ и сравниваю его с оригиналом, чтобы увидеть, изменилось ли что-нибудь:

set PATH_NQ=%PATH:"=%
if not "%PATH_NQ%"=="%PATH_NQ:c:\mydir=%" goto already_in_path
set PATH=%PATH%;c:\mydir
:already_in_path

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

set myPath=<pathToEnsure | %1>
echo ;%PATH%; | find /C /I ";%myPath%;" >nul
if %ERRORLEVEL% NEQ 0 set PATH=%PATH%;%myPath%

Я взял вашу реализацию, используя цикл for, и расширил ее до чего-то, что повторяет все элементы пути. Каждая итерация цикла for удаляет первый элемент пути (%p) из всего пути (содержится в%q и%r).

@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

Эта версия работает довольно хорошо. Он просто проверяет, находится ли vim71 в пути, и добавляет его, если нет.

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

Эта демонстрация иллюстрирует логику уровня ошибки:

@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 логика обратная, поскольку уровень ошибки 1 эквивалентен уровню ошибки>= 1. Из этого следует, что уровень ошибки 0 всегда будет иметь значение true, поэтому " not errorlevel 1 " используется.

Проверка PostScript может не потребоваться, если вы используете setlocal и endlocal для локализации настроек вашей среды, например

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

После endlocal вы вернетесь к исходному пути.

Добавить каталог в 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%)

Если ваш вопрос был "почему этот фрагмент сценария cmd не работает?" тогда ответ таков for /f перебирает строки. delims разбить строки на поля, но вы захватываете только первое поле в %%P, Там нет никакого способа, чтобы захватить произвольное количество полей с for /f петля.

Вы упоминаете, что хотите избежать добавления каталога в путь поиска, если он там уже существует. Вы намерены хранить каталог постоянно по пути или просто временно для пакетного файла?

Если вы хотите добавить (или удалить) каталоги навсегда в PATH, посмотрите на утилиту Path Manager (pathman.exe) в инструментах Windows Resource Kit для административных задач, http://support.microsoft.com/kb/927229. При этом вы можете добавлять или удалять компоненты как системных, так и пользовательских путей, и это будет обрабатывать аномалии, такие как повторяющиеся записи.

Если вам нужно только временно изменить путь для командного файла, я бы просто добавил дополнительный путь перед путем, с риском небольшого снижения производительности из-за дублирования записи в пути.

Просто в качестве альтернативы:

  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. Составление глобально уникального имени файла в уме не может считаться очень надежным. Создание такого имени само по себе не является тривиальной задачей.

Комментарий к скрипту addPath; При заполнении пути пробелами он выбрасывает.

Пример: вызов addPath "c:\Program Files (x86)\Microsoft SDKs\Windows\v7.0A\Bin"

выход: "Файлы" не распознаются как внутренняя или внешняя команда, работающая программа или пакетный файл.

Вы можете сделать это с помощью PoweShell;

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

Это возвращает TRUE или же FALSE

Коротко, просто и легко!

Основываясь на ответе 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

Это вариант ответа Кевина Эдвардса с использованием замены строк. Основной шаблон:

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

Например:

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

Короче говоря, мы делаем условный тест, в котором мы пытаемся удалить / заменить new_path от нашего PATH переменная окружения. Если new_path не существует условие успешно и new_path будет добавлен к PATH в первый раз. Если new_path уже существует, то условие не выполняется, и мы не будем добавлять new_path второй раз.

В общем, это поставить exe/dll на путь. Пока этот файл не появится где-либо еще:

@echo off
where /q <put filename here>    
if %errorlevel% == 1 (
    setx PATH "%PATH%;<additional path stuff>"
) else (
    echo "already set 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
)
      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%"
)

-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
}
Другие вопросы по тегам