Reputation: 341
I found a solution to remove a certain directory from the environment variable PATH directly via Windows commandline. But I would like to achieve the same result by issuing the command from within a cmd file.
What I can do is echoing the result I want to set PATH to if I put
echo %PATH:D:\dir-path;=%
into my cmd file. But if I write
set PATH=%PATH:D:\dir-path;=%
PATH contains only the directory I wanted to remove.
Furthermore I want to use a variable for the director path but if I try that the result is even worse. I put
set dirPath=D:\dir-path
echo %PATH:%dirPath%;=%
and all I get is dirPath;=
.
I don't know how to fix this so I would be really grateful if someone could assist.
EDIT 1
As suggested by @Anders I now have:
@echo off
set exampleRemoveDir=d:\bar
REM If I use %exampleRemoveDir% it does not work at all.
call :removeFromPath exampleRemoveDir & set result=%ERRORLEVEL%
:removeFromPath
set removeDir=%~1
setlocal enableextensions enabledelayedexpansion
set _=!PATH:%removeDir%;=!
if "%_%" == "%PATH%" set _=!PATH:%removeDir%=!
endlocal & set PATH=%_%
echo %PATH%
exit /b 0
But with that solution PATH still remains unchanged. The code works flawlessly if I don't scope the removing step bit since I want to do that for multiple directories it would be a real pain to not have such a nice helper doing the work for me.
EDIT 2
Since this seems to be more complex than I thought here is my complete unchanged script so far.
@echo off
:: Switching Perl version from ActivePerl to StrawberryPerl or the other way round depending on which paths are set in
:: PATH.
:: Directories for ActivePerl
set activePerl_SiteBinPath=D:\ProgramFiles\ActivePerl\site\bin
set activePerl_BinPath=D:\ProgramFiles\ActivePerl\bin
:: Directories for StrawberryPerl
set strawberryPerl_SiteBinPath=D:\ProgramFiles\StrawberryPerl\perl\site\bin
set strawberryPerl_BinCPath=D:\ProgramFiles\StrawberryPerl\c\bin
set strawberryPerl_BinPath=D:\ProgramFiles\StrawberryPerl\perl\bin
:: Determine which of the directories are present in PATH and which are not.
call :isInPath %activePerl_SiteBinPath% & set foundActivePerl_SiteBinPath=%ERRORLEVEL%
call :isInPath %activePerl_BinPath% & set foundActivePerl_BinPath=%ERRORLEVEL%
call :isInPath %strawberryPerl_SiteBinPath% & set foundStrawberryPerl_SiteBinPath=%ERRORLEVEL%
call :isInPath %strawberryPerl_BinCPath% & set foundStrawberryPerl_BinCPath=%ERRORLEVEL%
call :isInPath %strawberryPerl_BinPath% & set foundStrawberryPerl_BinPath=%ERRORLEVEL%
:: Test
call :removeFromPath %strawberryPerl_SiteBinPath% & set removedStrawberryPerl_SiteBinPath=%ERRORLEVEL%
rem if /i %foundActivePerl_SiteBinPath% equ 0 if /i %foundActivePerl_BinPath% equ 0 (
rem if /i %foundStrawberryPerl_SiteBinPath% neq 0 if /i %foundStrawberryPerl_BinPath% neq 0 if /i %foundStrawberryPerl_BinCPath% neq 0 (
rem echo Switching from ActivePerl to StrawberryPerl.
rem TODO
rem exit /b 0
rem )
rem )
rem
rem if /i %foundStrawberryPerl_SiteBinPath% equ 0 if /i %foundStrawberryPerl_BinPath% equ 0 if /i %foundStrawberryPerl_BinCPath% equ 0 (
rem if /i %foundActivePerl_SiteBinPath% neq 0 if /i %foundActivePerl_BinPath% neq 0 (
rem echo Switching from StrawberryPerl to ActivePerl.
rem TODO
rem exit /b 0
rem )
rem )
:: Error
:: TODO
exit /b
:isInPath
:: 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 pathVar path is not found in %PATH%.
:: 2 if parhVar path is missing or undefined.
:: Error checking
if "%~1"=="" exit /b 2
set pathVar=%~1
for /f %%i in ('echo ";%%PATH%%;" ^| find /c /i ";%pathVar%;"') do set /a foundPathVar=%%i
if /i %foundPathVar% equ 0 (
exit /b 1
)
exit b/ 0
:removeFromPath
:: Removes a given directory from environment variable PATH if the directory exists within PATH.
::
:: The result is returned as the ERRORLEVEL:
:: 0 if the given directory was removed from PATH or if it didn't exist in PATH.
:: 1 if no directory was given or the directory is undefined.
:: Error checking
if "%~1"=="" exit /b 2
set removeDir=%~1
setlocal enableextensions enabledelayedexpansion
set _=!PATH:%removeDir%;=!
if "%_%" == "%PATH%" set _=!PATH:;%removeDir%=!
endlocal & set PATH=%_%
echo %PATH%
exit /b 0
EDIT 3
Thanks to @Anders removing the directory from path now works fine. I removed the wrong check for undefined parameter above and add %
around the parameter of function calls.
But somehow :isInPath
now always returns zero. As far as I am concerned this already worked... :/ Furthermore, with the current code (added %
to all function parameters) the cmd always directly closes irrespective of a pause
after the call of :removeFromPath
. It's infuriatingly!
Upvotes: 1
Views: 6390
Reputation: 101756
You need to use delayed expansion if you want to use another variable as part of the variable substitution. You also need to deal with the possibility that the path you want to remove is at the end of %path%
and therefore not terminated by a ;
.
@echo off
set removedir=d:\bar
set PATH=c:\foo;%removedir%;y:\baz&REM Set example %path%
echo Starting with %%PATH%% set to %PATH%
setlocal enableextensions enabledelayedexpansion
set _=!PATH:%removedir%;=!
if "%_%" == "%PATH%" set _=!PATH:;%removedir%=!
endlocal & set PATH=%_%
echo %%PATH%% is now %PATH%
and here as a helper function:
@echo off
goto start
:removeFromPath
echo.Debug: Starting function with remove=%~1 and %%PATH%%=%PATH%
setlocal enableextensions enabledelayedexpansion
set removedir=%~1
set _=!PATH:%removedir%;=!
if "%_%" == "%PATH%" set _=!PATH:;%removedir%=!
endlocal & set PATH=%_%
echo.Debug: Ending function with %%PATH%%=%PATH%
goto :EOF
:start
set exampleremovedir=d:\bar
set PATH=c:\foo;%exampleremovedir%;y:\baz&REM Set example %path%
echo Starting with %%PATH%% set to %PATH%
call :removeFromPath %exampleremovedir%
echo %%PATH%% is now %PATH%
Upvotes: 2