it-swarm.com.ru

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

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

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

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

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

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

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

Правка: Добавлен флаг без учета регистра, благодаря Panos.

36
Randy

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

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

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

21
bert bruynooghe

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

Используя 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%"
6
Atif Aziz

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

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.

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

4
mousio

Я взял вашу реализацию, используя цикл 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
2
indiv

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

2
Adam Mitz

Вы также можете использовать замену подстроки, чтобы проверить наличие подстроки. Здесь я удаляю кавычки для создания 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
2
Kevin Edwards

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

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

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

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

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

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

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

1
Heyvoon

Просто для уточнения ответа Heyvoon's (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
1
Albert

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

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

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

1
Andriy M

Эта версия работает довольно хорошо. Он просто проверяет, находится ли 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 вы вернетесь к исходному пути.

1
Chris Degnen

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

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 во второй раз.

1
Stephen Quan

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

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

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

1
Morten Grøtan

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

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

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

1
ketorin

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

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

Эта подпрограмма будет искать путь\или 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
)
0
carlsomo