command-linebatch-fileenvironment-variablespathappend

Why is appending to User Environment Variable PATH without duplicating is not working for the last path in Windows 11 command line?


I looked through a few solutions here and found an almost working script to append to the user Environment Variable PATH without overwriting the existing path and not clutter it with system's EV's PATH.

I wanted to add 4 paths, 2 from Python and 2 from Anaconda. The first 3 locations work perfectly (Python311, Python312, conda.exe), but it keeps duplicating the 4th path (_conda.exe) even though the script sequence is the same.

Thoughts?

@echo off
REM usage: append_user_path "path"
SET Key="HKCU\Environment"
FOR /F "usebackq tokens=2*" %%A IN (`REG QUERY %Key% /v PATH`) DO Set CurrPath=%%B
echo Add %appdata%\Python\Python311\Scripts to PATH
@echo off
set "newPath=%appdata%\Python\Python311\Scripts"
echo %CurrPath% | findstr /i /c:"%newPath%" >nul
if errorlevel 1 (
    setx PATH "%CurrPath%;%newPath%"
    echo Path updated successfully.
) else (
    echo Path already contains the directory.
)

REM usage: append_user_path "path"
SET Key="HKCU\Environment"
FOR /F "usebackq tokens=2*" %%A IN (`REG QUERY %Key% /v PATH`) DO Set CurrPath=%%B
echo Add %appdata%\Python\Python312\Scripts to PATH
@echo off
set "newPath=%appdata%\Python\Python312\Scripts"
echo %CurrPath% | findstr /i /c:"%newPath%" >nul
if errorlevel 1 (
    setx PATH "%CurrPath%;%newPath%"
    echo Path updated successfully.
) else (
    echo Path already contains the directory.
)

REM usage: append_user_path "path"
SET Key="HKCU\Environment"
FOR /F "usebackq tokens=2*" %%A IN (`REG QUERY %Key% /v PATH`) DO Set CurrPath=%%B
echo Add %ProgramFiles%\Continuum\Anaconda3\conda.exe to PATH
@echo off
set "newPath=%ProgramFiles%\Continuum\Anaconda3\conda.exe"
echo %CurrPath% | findstr /i /c:"%newPath%" >nul
if errorlevel 1 (
    setx PATH "%CurrPath%;%newPath%"
    echo Path updated successfully.
) else (
    echo Path already contains the directory.
)

REM usage: append_user_path "path"
SET Key="HKCU\Environment"
FOR /F "usebackq tokens=2*" %%A IN (`REG QUERY %Key% /v PATH`) DO Set CurrPath=%%B
echo Add %ProgramFiles%\Continuum\Anaconda3\_conda.exe to PATH
@echo off
set "newPath=%ProgramFiles%\Continuum\Anaconda3\_conda.exe"
echo %CurrPath% | findstr /i /c:"%newPath%" >nul
if errorlevel 1 (
    setx PATH "%CurrPath%;%newPath%"
    echo Path updated successfully.
) else (
    echo Path already contains the directory.
)
Pause

Append path works as intended for the first 3 paths if they already exist. But even if the 4th path exists, it appends/adds/duplicates it anyway:

Screenshot of above's explanation:


Solution

  • This is a quirk of findstr:

    The findstr string parser handles a backslash followed by a non alphanumeric character as a single escaped character. That is

    REM searches for just _, finds it
    echo _ | findstr \_
    _
    
    REM searches for literally \a, finds nothing
    echo a | findstr \a
    
    

    \_ becomes just _ in the search string, so the script searches the path for ...Anaconda3_conda.exe which is not there. Escape the backslash to search for a backslash followed by a non alphanumeric character: \\_ becomes \_ in the search string.

    set "newPath=%ProgramFiles%\Continuum\Anaconda3\\_conda.exe"
    

    would do what you want, but you only need directory entries in the path. Which I would not let end on a trailing backslash because of such problems.