PATH issues

Discussion forum for all Windows batch related topics.

Moderator: DosItHelp

Post Reply
Message
Author
dbenham
Expert
Posts: 2383
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

PATH issues

#1 Post by dbenham » 29 Oct 2011 14:54

Fairly frequently I want to examine the PATH contents, and it is really a pain to visually parse when it contains many paths. I grew tired of copying the value to a text editor and adding new lines manually. I figured there must be a way to programmatically split the path into multiple lines appropriately.

I came up with the following (to be executed on the command line)

Code: Select all

for %P in ("%path:;=" "%") do @echo(%~P

It worked great, and I was curious if anyone had posted it before.

Of course jeb has already posted a nearly identical solution at 'Pretty print' windows %PATH% variable - how to split on ';' in CMD shell :mrgreen:

jeb goes on to show how the solution fails if the PATH contains quoted ; within it. The problem is ; is a valid character for folder names, and must be quoted in the PATH. He posted a safe solution for any situation on the same thread. I won't post his safe solution here (nor some minor improvements I suggested). Just follow the link.


I then started thinking about PATH, and how it is common practice to append to PATH using something like:

Code: Select all

set PATH=%PATH%;c:\new_path\

Even Microsoft recommends the operation:

Code: Select all

C:\>help path
Displays or sets a search path for executable files.

PATH [[drive:]path[;...][;%PATH%]
PATH ;

Type PATH ; to clear all search-path settings and direct cmd.exe to search
only in the current directory.
Type PATH without parameters to display the current path.
Including %PATH% in the new path setting causes the old path to be
appended to the new setting.

But this will fail if the PATH contains any of the following valid unquoted path characters: ^ &

This fix is not reliable:

Code: Select all

set "path=%path%;\new_path"
because the PATH may already contain quotes. In fact, the PATH must contain quotes if any path includes the ; character.

Here is a valid PATH that wont extend properly either with or without enclosing quotes:

Code: Select all

PATH=c:\This & That;"c:\A path with ; semicolon";c:\a third path



The solution is fairly simple - make sure the PATH is expanded using delayed expansion.

Here is a simple function that will reliably append any path to the existing PATH as long as it is not called while delayed expansion is enabled. (thanks Ed for pointing out this limitation in your post below).

Code: Select all

@echo off
:PathAdd pathVar
:: pathVar is the name of a variable containing the new path to append to PATH
setlocal enableDelayedExpansion
for /f "tokens=* delims=;" %%N in ("!%~1!") do (
  for /f "tokens=* delims=;" %%P in ("!PATH!") do (
    endlocal
    set path=%%P;%%N
  )
)
exit /b


Dave Benham
Last edited by dbenham on 12 Nov 2011 10:47, edited 1 time in total.

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: PATH issues

#2 Post by Ed Dyreen » 29 Oct 2011 20:04

'
I just don't understand why it apparently is so important for some (dBenham) to always stay in disable delayed.
I default to delayed, and when I need it, I can always switch to disabled.
The only reason I can think of would be if you are working from the terminal where setlocal doesn't apply.

What is so GOOD about disable delayed, because all I am having with it are problems having to escape special chars.
You can't even do the simplest thing in disable delayed: :?:

Code: Select all

set "$var=%$var%"
The contents may have changed !, did you use escapes ? o well, that's too bad.

dbenham
Expert
Posts: 2383
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: PATH issues

#3 Post by dbenham » 12 Nov 2011 11:17

I want to do my part to let Ed relax and sleep well at night :roll:
So here is a version that can be called with delayed expansion enabled or disabled

Code: Select all

@echo off
:PathAdd pathVar
:: pathVar is the name of a variable containing the new path to append to PATH
setlocal
set "NotDelayed=!"
setlocal enableDelayedExpansion
set "rtn=!path!;!%~1!"
set "rtn=!rtn:%%=%%~A!"
set "rtn=!rtn:"=%%~B!"
if not defined NotDelayed set "rtn=!rtn:^=^^^^!"
if not defined NotDelayed set "rtn=%rtn:!=^^^!%" !
set "replace=%% """"
for /f "tokens=1,2" %%A in ("!replace!") do (
  endlocal & endlocal
  set "path=%rtn%" !
)
exit /b

We don't need <CR> or <LF> support so I used a simplified version of jeb's safe return technique.

Dave Benham

Ed Dyreen
Expert
Posts: 1569
Joined: 16 May 2011 08:21
Location: Flanders(Belgium)
Contact:

Re: PATH issues

#4 Post by Ed Dyreen » 13 Nov 2011 03:45

'
You are too nice for me, I wasn't going to use the path anyways, never, I already hate the fact that ATI is in there, who the hell they think they are.

No, I just made a habbit of it to always address external sources by absolute sourcename.

dbenham
Expert
Posts: 2383
Joined: 12 Feb 2011 21:02
Location: United States (east coast)

Re: PATH issues

#5 Post by dbenham » 13 Nov 2011 19:38

Another common PATH question is "How do I determine if mypath already exists within PATH? - If it doesn't, append it"

It is surprisingly difficult to get a safe, reliable solution that works in all situations.

I've documented many issues that plague this problem, as well as the best solution I could come up with, at StackOverflow: How to check if directory exists in %PATH%?

It's a good read if you have any DOS geek in you. It even has the jeb stamp of approval :)

Dave Benham

foxidrive
Expert
Posts: 6033
Joined: 10 Feb 2012 02:20

Re: PATH issues

#6 Post by foxidrive » 15 Mar 2012 19:44

dbenham wrote:Another common PATH question is "How do I determine if mypath already exists within PATH? - If it doesn't, append it"

It is surprisingly difficult to get a safe, reliable solution that works in all situations.


There are lots of gotchas in the path as outlined there. An interesting read, though I didn't read it fully.

However, how about using this to test if a directory is on the path:

Code: Select all

@echo off
set "folder=c:\to the\path to test"
md "%folder%" 2>nul
echo @echo abc>"%folder%\dang fool, don't run me.bat"
pushd "c:\"
set "var="
for /f "delims=" %%a in ('"dang fool, don't run me.bat" 2^>nul') do set "var=%%a"
if defined var (
echo Yes, the "%folder%" is on the path.
) else (
echo Nope, "%folder%" ain't on the path"
)
del "%folder%\dang fool, don't run me.bat" 2>nul
popd
pause


It won't work if the folder is on an optical/read-only media but I think it should handle any other case.

Post Reply