Ответ 1
edit: После некоторого тестирования выясняется, что мой первоначальный ответ не совсем применим к вопросам OP. Чтобы напрямую ответить OP:
-
%PATH%
объединяет значения вHKLM\System\CurrentControlSet\Control\Session Manager\Environment\Path
сHKCU\Environment\Path
. Когда выsetx "dir;dir"
, вы устанавливаете значениеHKEY_CURRENT_USER
Path
. Значение машинного значенияHKEY_LOCAL_MACHINE
Path
остается нетронутым. Вот почему вы видите свои значения как добавленные, а не как замены. Вы должны использоватьsetx /m
для замены значенияHKLM
Path
. Но не делайте этого, если не хотите создавать серьезные проблемы при установке вашей операционной системы. -
Если вы хотите проверить, существует ли каталог в
%PATH%
, вы могли быcd
илиpushd
оба в каталог, который вы хотите проверить, и каждый каталог в%PATH%
, чтобы объединить их, что делает убедитесь, что все относительные пути, переменные среды и т.д. сплющены.set "var=%CD%"
для каждого. Затемif /I "!dir1!"=="!dir2!"
каталог уже существует где-то в%PATH%
. Вот пример этого в моем первоначальном ответе ниже.
Причина, по которой мой первоначальный ответ не совсем применим, состоит в том, что сам setx
не так разрушителен, как я когда-то думал. Опасность заключается в том, что часто, когда пользователи хотят добавить каталог на свой путь, они будут setx /m PATH "%PATH%;new dir"
; и это разрушительно. Поскольку %PATH%
раскрывается до того, как setx
записывает значение, все каталоги в PATH распаковываются преждевременно.
Следующий метод будет более безопасным:
set "env=HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
for /f "tokens=2*" %%I in (
'reg query "%env%" /v Path ^| findstr /i "\<Path\>"'
) do setx /m PATH "%%J;new directory"
Но это не совсем то, что спросил ОП, и я извиняюсь за ответ на коленный рефлекс.
оригинальный ответ: setx
является разрушительным и не должен использоваться таким образом. Когда вы setx PATH
, вы преобразовываете тип данных значения реестра из REG_EXPAND_SZ в REG_SZ. Как только вы это сделаете, все динамические переменные среды, хранящиеся в вашем% PATH%, будут преобразованы в плоские, абсолютные пути. Используйте команду Path
для временного добавления каталогов на ваш %PATH%
и reg add
, чтобы сделать это постоянно. (В качестве дополнительной заметки также есть dpath
, который временно добавляет каталог к вашему пути, но может использоваться только командой type
. Прокрутка 2/3 вниз эту страницу для получения дополнительной информации о dpath
.)
Здесь утилита script я написал, чтобы добавить каталоги в мой %PATH%
менее разрушительным образом. Он также не будет добавлять один и тот же каталог в %PATH%
более одного раза, независимо от того, как он отформатирован (например, обратная косая черта, относительные пути, переменные среды или любая другая перестановка).
@echo off
setlocal enabledelayedexpansion
if not exist "%~1" goto usage
for %%I in ("%~1") do pushd "%%~I" 2>NUL && (set "new=!CD!" && popd) || goto usage
for %%I in ("%PATH:;=";"%") do pushd "%%~I" 2>NUL && (
rem // delaying expansion of !new! prevents parentheses from breaking things
if /i "!new!"=="!CD!" (
echo !new! already exists in %%PATH%%
goto :EOF
)
popd
)
call :append_path "%new%"
goto :EOF
:usage
echo Usage: %~nx0 "dir"
goto :EOF
:append_path <val>
set "env=HKLM\System\CurrentControlSet\Control\Session Manager\Environment"
for /f "tokens=2*" %%I in ('reg query "%env%" /v Path ^| findstr /i "\<Path\>"') do (
rem // make addition persistent through reboots
reg add "%env%" /f /v Path /t REG_EXPAND_SZ /d "%%J;%~1"
rem // apply change to the current process
for %%a in ("%%J;%~1") do path %%~a
)
rem // use setx to set a temporary throwaway value to trigger a WM_SETTINGCHANGE
rem // applies change to new console windows without requiring a reboot
(setx /m foo bar & reg delete "%env%" /f /v foo) >NUL 2>NUL
color 4E
echo Warning: %%PATH%% has changed. Reopen the console to inherit the changes.
goto :EOF