1

I'm creating a bat script and I should check whether a variable contains a valid absolute path of a directory and if another variable contains a valid name of a file for Windows 8 and above.

So, how would I go these checks?

Thanks

Bye

Balubeto
  • 11
  • 1
  • 2

2 Answers2

8

This is much trickier than most people realize. There is lots of misinformation about this topic available on SO and elsewhere. There are many "solutions" that appear to work, but then fail under certain circumstances.

The problem can be divided into two parts:

1) Absolute or Relative

You cannot simply convert the path into a full path using FOR variable "%%~fF" or parameter "%~f1" and test to see if it matches the original string (ignoring case) because there are an infinite number of ways an absolute path can be written. A valid absolute path may have any number of \..\ or \.\ within it. Also, an absolute path may use a drive letter or it may be a UNC path. Also, an absolute path may include any number of " within it.

I test to see if a path is absolute or relative by first removing all quotes, and then I use FINDSTR to test if it begins with either of the following:

  • Drive letter, followed by colon, followed by backslash
  • Two back slashes

2) File or Folder or Not exists

It is easy to use IF EXISTS path to tell whether a path is valid or not. But it is more difficult to distinguish a file from a folder.

Back in the days of DOS, you could check if path\NUL exists, and if it does, then you knew that path was a folder. Unfortunately, many people are under the false impression that this works under Windows - It is not reliable under Windows

Another frequent attempt is to test if path\ exists, and if so, assume that it must be a folder. This often seems to work, but it does not work if the path involves directory symbolic links or junctions

The classification code I would use is nearly the same as for https://stackoverflow.com/a/8669636/1012053, except I have adopted it for use with an environment variable instead of a batch parameter.

I use the FOR variable ~a modifier to look at the file/folder attributes. If I find d then it is a folder. if I find attributes without d then it is a file. Else if I fail to find attributes then it does not exist.

The other method that appears to accurately tell whether a folder exists is to test if path\* exists, but I have less experience with this method.


So putting it all together, I get

@echo off
setlocal
set var=test.bat

setlocal enableDelayedExpansion

:: Determine absolute or relative
echo(!var:^"=!|findstr /i "^[A-Z]:[\\] ^[\\][\\]" >nul && set "type=absolute" || set "type=relative"

:: Determine file or folder or not exists
for /f eol^=^ delims^= %%F in ("!var!") do (
  for /f "tokens=1,2 delims=d" %%A in ("-%%~aF") do if "%%B" neq "" (
    echo %%F = %type% folder
  ) else if "%%A" neq "-" (
    echo %%F = %type% file
  ) else (
    echo %%F does not exist
  )
)
Community
  • 1
  • 1
dbenham
  • 127,446
  • 28
  • 251
  • 390
  • Nice answer. By the way, does the paren in echo(!var... have some purpose? – wolfrevokcats Jul 03 '16 at 16:29
  • 1
    @wolfrevokcats - I used `ECHO(` instead of `ECHO ` just in the off chance the result of the expansion is an empty string (or spaces only). But I just realized it gives the correct answer either way. ECHOing a blank or empty string without `(` will yield `ECHO is off.`, which will result in determination of "relative". But the 2nd part will determine "does not exist" (the correct answer). End result - No, there is not a good reason to use `echo(`, but it doesn't hurt either. – dbenham Jul 03 '16 at 16:37
  • Is there a particular technical reason why you are specifying character classes for backslashes `[\\]` instead of `\\` only, or is it just for legibility? – aschipfl Jul 04 '16 at 21:47
  • 1
    @aschipfl - Yes. Normally you can use \\, but there are some circumstances where it does not work. But `[\\]` always works. Rather than try to remember what works where, I always use `[\\]`. I talk about it at [What are the undocumented features and limitations of the Windows FINDSTR command?](http://stackoverflow.com/q/8844868/1012053) – dbenham Jul 04 '16 at 21:54
  • Ah, yes, I found that "feature" (\\ and \") in your linked answer, thank you! (actually I meant using \\ in my [previous comment](http://stackoverflow.com/questions/38169201/check-if-an-absolute-path-of-a-directory-or-a-file-name-are-valid/38170999#comment63810653_38170999) but one disappeared as I enclosed them in ``...) So `[\\]` totally makes sense! – aschipfl Jul 04 '16 at 23:19
  • @aschipfl - I've been bit by the problem of \\ formatted as in-line code within comments as well. I figured that is what you meant :-) – dbenham Jul 05 '16 at 01:51
0

Here is the self-explanatory code. It expects an argument containing the path to check.

set "INPUT_PATH=%~1"
set "FULL_PATH=%~f1"
set "SHORT_PATH=%~s1"
if /i "%INPUT_PATH%"=="%FULL_PATH%" echo this is a full path 
if exist "%INPUT_PATH%" echo this is an existing path
if exist %SHORT_PATH%\NUL echo this is a directory
wolfrevokcats
  • 2,100
  • 1
  • 12
  • 12
  • 1
    Nope. Your absolute path test can fail in the presence of `..`, `.`, `"`, or UNC path. The `%short_path%\nul` test is intriguing, but fails if short 8.3 paths are disabled for the volume. See [my answer](http://stackoverflow.com/a/38170999/1012053) – dbenham Jul 03 '16 at 14:43