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

<p>как проверить, присутствует ли каталог в переменной среды path? вот начало. все, что мне удалось сделать с помощью приведенного ниже кода, - это отобразить первый каталог в% path%. поскольку это цикл for, можно подумать, что он перечислит все каталоги в% path%, но он получит только первый.</p><p>есть ли лучший способ сделать это? что-то вроде find или findstr, работающего с переменной% path%? я просто хотел бы проверить, существует ли каталог в списке каталогов в% path%, чтобы избежать добавления чего-то, что уже может быть там.</p><pre><code>for /f "delims=;" %%p in ("%path%") do ( @echo %%~p ) </code></pre>

<p>я давно не занимался программированием пакетных файлов, но:</p><pre><code>echo ;%path%; | find /c /i ";<string>;" </code></pre><p>должен дать вам 0, если строка не найдена, и 1 или более, если она есть.</p><p>правка: добавлен флаг без учета регистра, благодаря panos.</p>

<p>другой способ проверить, находится ли что-то в пути, состоит в том, чтобы выполнить невинный исполняемый файл, который не потерпит неудачу, если он там есть, и проверить результат. например, следующий фрагмент кода проверяет, находится ли <strong>maven</strong> в пути:</p><pre><code>mvn --help > nul 2> nul if errorlevel 1 goto mvnnotinpath </code></pre><p>поэтому я пытаюсь запустить <em> mvn --help </em>, игнорировать вывод (на самом деле не хочу видеть помощь, если есть maven) (> nul) , а также не отображать сообщение об ошибке, если maven не был найден (2> nul).</p>

<p>прочитав ответы здесь, я думаю, что могу представить новую точку зрения: если целью этого вопроса является знать <em>, если путь к определенному исполняемому файлу </em> существует в <code>%path%</code> и, если нет, вставьте его (и <strong>это единственная причина</strong> для этого, я думаю), тогда это может быть решено немного по-другому: "как проверить, является ли каталог определенная исполняемая программа существует в% path% "? этот вопрос может быть легко решен следующим образом:</p><pre><code>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:pathtoprogranname" ) если вы не знаете расширения исполняемого файла, просто просмотрите все из них:set "progpath=" for %%e in (%pathext%) do ( if not defined progpath ( for %%p in (programname.%%e) do set "progpath=%%~$path:p" ) ) </code></pre>

<p>используя <a href="http://technet.microsoft.com/en-us/library/bb490909.aspx"><code>for</code></a> и <a href="http://technet.microsoft.com/en-us/library/bb490909.aspx"><code>delims</code></a> , вы не можете захватить произвольное количество полей (как <a href="https://stackoverflow.com/questions/141344/how-to-check-if-directory-exists-in-path#142381">также указал адам</a> ), поэтому вы должны использовать технику зацикливания вместо. следующий командный сценарий перечислит каждый путь в переменной среды <code>path</code> в отдельной строке:</p><pre><code>@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 </code></pre><p>он имитирует классическую <em> while </em>… <em> wend </em> конструкцию, найденную во многих языках программирования. имея это в виду, вы можете использовать что-то вроде <a href="http://technet.microsoft.com/en-us/library/bb490907.aspx"><code>findstr</code></a> для последующей фильтрации и поиска определенного пути. например, если вы сохранили вышеупомянутый скрипт в файле с именем <code>tidypath.cmd</code>, то вот как вы могли бы перенаправить на <code>findstr</code>, ища пути в каталоге стандартных программ (используя сопоставление без учета регистра):</p><pre><code>> tidypath | findstr /i "%programfiles%" </code></pre>

<p>это будет искать точное, но нечувствительное к регистру совпадение, так что не забывайте о конце и т.д.</p><pre><code>for %p in ("%path:;=";"%") do @if /i %p=="path\_to\_check" echo %p exists in path </code></pre><p>или в пакетном файле (например, checkpath.bat), который принимает аргумент:</p><pre><code>@for %%p in ("%path:;=";"%") do @if /i %%p=="%~1" echo %%p exists in path </code></pre><p>в последнем виде можно назвать, например, <code>checkpath "%programfiles%"</code>, чтобы увидеть, существует ли указанный путь в path.</p><p>обратите внимание, что эта реализация предполагает отсутствие точек с запятой или кавычек внутри одного элемента пути.</p>

<p>я взял вашу реализацию, используя цикл <em>for</em>, и расширил ее до чего-то, что повторяет все элементы пути. каждая итерация цикла for удаляет первый элемент пути (% p) из всего пути (содержится в% q и% r).</p><pre><code>@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 </code></pre><p>образец вывода:</p><pre><code>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 </code></pre>

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

<p>вы также можете использовать замену подстроки, чтобы проверить наличие подстроки. здесь я удаляю кавычки для создания path\_nq, затем я удаляю "c:\mydir" из path\_nq и сравниваю его с оригиналом, чтобы увидеть, изменилось ли что-нибудь:</p><pre><code>set path\_nq=%path:"=% if not "%path\_nq%"=="%path\_nq:c:\mydir=%" goto already\_in\_path set path=%path%;c:\mydir :already\_in\_path </code></pre>

<p>добавить каталог в path, если он еще не существует:</p><pre><code>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%) </code></pre>

<p>я объединил некоторые из приведенных выше ответов, чтобы придумать это, чтобы гарантировать, что заданная запись пути существует <em>в точности как указано</em> с максимально возможной краткостью и без ненужного эха в командной строке.</p><pre><code>set mypath=<pathtoensure | %1> echo ;%path%; | find /c /i ";%mypath%;" >nul if %errorlevel% neq 0 set path=%path%;%mypath% </code></pre>

<p>вы можете сделать это с помощью powershell;</p><pre><code>test-path $env:systemrootyourdirectory test-path c:windowsyourdirectory это возвращает true или falseкоротко, просто и легко!

просто для уточнения ответа <a href="https://stackoverflow.com/a/30711326/2211788">heyvoon's (2015.06.08) с помощью powershell, этот простой скрипт powershell должен дать вам подробную информацию о% path%$env:path -split ";" | % {"$(test-path $\_);$_"} генерируя этот вид вывода, который вы можете проверить самостоятельноtrue;c:windows true;c:windowssystem32 true;c:windowssystem32wbem false;c:windowssystem32windowspowershellv1.0 false;c:program files (x86)javajre7bin пересобрать для обновления path:$x=$null;foreach ($t in ($env:path -split ";") ) {if (test-path $t) {$x+=$t+";"}};$x 

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

просто в качестве альтернативы:  в папке, в которой вы будете искать переменную path, создайте временный файл с таким необычным именем, что вы никогда не ожидаете, что какой-либо другой файл на вашем компьютере будет иметься.   используйте стандартную конструкцию пакетного сценария, которая позволяет выполнять поиск файла путем поиска списка каталогов, определенного некоторой переменной среды (обычно path).   проверьте, соответствует ли результат поиска указанному пути, и отобразите результат.   удалить временный файл.  это может выглядеть так:@echo off set "mypath=d:thesearched-forpath" 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 ) </code></pre><p>известные вопросы:</p><ol> <li> <p>метод может работать, только если каталог существует (что не всегда так).</p> </li> <li> <p>создание/удаление файлов в каталоге влияет на его атрибут "измененная дата/время" (что иногда может быть нежелательным эффектом).</p> </li> <li> <p>составление глобального уникального имени файла в уме не может считаться очень надежным. создание такого имени само по себе не является тривиальной задачей.</p> </li> </ol>

<p>эта версия работает довольно хорошо. он просто проверяет, находится ли vim71 в пути, и добавляет его, если нет.</p><pre><code>@echo off echo %path% | find /c /i "vim71" > nul if not errorlevel 1 goto jump path = c:\program files\vim\vim71\;%path% :jump </code></pre><p>эта демонстрация иллюстрирует логику уровня ошибки:</p><pre><code>@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 </code></pre><p>в коде vim71 логика обратная, поскольку уровень ошибки 1 эквивалентен уровню ошибки> = 1. из этого следует, что уровень ошибки 0 всегда будет иметь значение true, поэтому используется "<code>not errorlevel 1</code>".</p><p><strong>postscript</strong> проверка может не потребоваться, если вы используете setlocal и endlocal для локализации настроек вашей среды, например,.</p><pre><code>@echo off setlocal path = c:\program files\vim\vim71\;%path% rem your code here endlocal </code></pre><p>после endlocal вы вернетесь к исходному пути.</p>

<p>это вариант ответа кевина эдвардса с использованием замены строк. основной шаблон:</p><pre><code>if "%path:new\_path=%" == "%path%" path=%path%;new\_path </code></pre><p>например:</p><pre><code>if "%path:c:\scripts=%" == "%path%" path=%path%;c:\scripts </code></pre><p>в двух словах, мы делаем условный тест, в котором мы пытаемся удалить/заменить <code>new\_path</code> из нашей переменной окружения <code>path</code>. если <code>new\_path</code> не существует, условие выполнено успешно и <code>new\_path</code> будет добавлен к <code>path</code> в первый раз. если <code>new\_path</code> уже существует, условие не выполняется, и мы не будем добавлять <code>new\_path</code> во второй раз.</p>

<p>комментарий к скрипту addpath; при заполнении пути пробелами он выбрасывает.</p><p>пример: вызов addpath "c:\program files (x86)\microsoft sdks\windows\v7.0a\bin"</p><p>результат: "файлы" не распознаются как внутренняя или внешняя команда, работающая программа или командный файл.</p>

<p>вы упоминаете, что хотите избежать добавления каталога в путь поиска, если он там уже существует. вы намерены хранить каталог постоянно по пути или просто временно для пакетного файла?</p><p>если вы хотите навсегда добавить (или удалить) каталоги в path, посмотрите на утилиту path manager (pathman.exe) в windows resource kit tools для административных задач <a href="http://support.microsoft.com/kb/927229">http://support.microsoft.com/kb/927229</a> . при этом вы можете добавлять или удалять компоненты как системных, так и пользовательских путей, и это будет обрабатывать аномалии, такие как повторяющиеся записи.</p><p>если вам нужно только временно изменить путь для командного файла, я бы просто добавил дополнительный путь перед путем, с риском небольшого снижения производительности из-за дублирования записи в пути.</p>

<p>в общем, это поставить exe/dll на путь. пока этот файл не появится где-либо еще:</p><pre><code>@echo off where /q <put filename here> if %errorlevel% == 1 ( setx path "%path%;<additional path stuff>" ) else ( echo "already set path" ) </code></pre>

<p>эта подпрограмма будет искать путь\или file.ext в переменной пути, она возвращает 0, если найдена. путь\или файл может содержать пробелы в кавычках. если переменная передается в качестве последнего аргумента, она будет установлена в <code>d:\path\file</code>.</p><pre><code>@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 ) </code></pre>