views:

7939

answers:

7

How does one check if a directory is already present in the PATH environment variable? Here's a start. All I've managed to do with the code below, though, is echo the first directory in %PATH%. Since this is a FOR loop you'd think it would enumerate all the directories in %PATH%, but it only gets the first one.

Is there a better way of doing this? Something like find or findstr operating on the %PATH% variable? I'd just like to check if a directory exists in the list of directories in %PATH%, to avoid adding something that might already be there.

FOR /F "delims=;" %%P IN ("%PATH%") DO (
    @ECHO %%~P
)
+1  A: 

I haven't done any batch file programming in a while, but:

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

should give you 0 if string is not found and 1 or more if it is.

EDIT: Added case-insensitive flag, thanks to Panos.

Randy
To be complete add the case-insensitive flag /I to find.
Panos
Thanks! I'll add that in.
Randy
Does this really solve Axl's problem? He wants to check if adding a directory, say C:\foo\bar to PATH would be redundant. Let's say his PATH already contained c:\foo, your check would say "yes, it's redundant" when it's actually not.
Adam Mitz
A: 

If your question was "why doesn't this cmd script fragment work?" then the answer is that for /f iterates over lines. The delims split lines into fields, but you're only capturing the first field in %%P. There is no way to capture an arbitrary number of fields.

Adam Mitz
+1  A: 

Building on rcar's answer, you have to make sure a substring of the target isn't found.

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
Adam Mitz
+1  A: 

I took your implementation using the for loop and extended it into something that iterates through all elements of the path. Each iteration of the for loop removes the first element of the path (%p) from the entire path (held in %q and %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

Sample output:

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
indiv
A: 

You mention that you want to avoid adding the directory to search path if it already exists there. Is your intention to store the directory permanently to the path, or just temporarily for batch file's sake?

If you wish to add (or remove) directories permanently to PATH, take a look at Path Manager (pathman.exe) utility in Windows Resource Kit Tools for administrative tasks, http://support.microsoft.com/kb/927229. With that you can add or remove components of both system and user paths, and it will handle anomalies such as duplicate entries.

If you need to modify the path only temporarily for a batch file, I would just add the extra path in front of the path, with the risk of slight performance hit because of duplicate entry in the path.

ketorin
+4  A: 

Using for and delims, you cannot capture an arbitrary number of fields (as Adam pointed out as well) so you have to use a looping technique instead. The following command script will list each path in the PATH environment variable on a separate line:

@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

It simulates a classical whilewend construct found in many programming languages. With this in place, you can use something like findstr to subsequently filter and look for a particular path. For example, if you saved the above script in a file called tidypath.cmd then here is how you could pipe to findstr, looking for paths under the standard programs directory (using a case-insensitive match):

> tidypath | findstr /i "%ProgramFiles%"
Atif Aziz
+1  A: 

Another way to check if something is in the path is to execute some innocent executable that is not going to fail if it's there, and check the result. As an example, next code snippet checks if maven is in the path:

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

So I try to run mvn --help, ignore the output (don't actually want to see the help if maven is there)( > NUL), and also don't display the error message if maven was not found (2> NUL).