Why does the cmd.exe shell on Windows fail with paths using a forward-slash ('/'') path separator?
Asked Answered
D

3

23

Just when I'd thought I'd seen it all with Windows path issues, I've now encountered a case that only fails when '/' (forward-slash) is used as the path separator is used:

C:\temp\tcbugs>mkdir "dir1 with spaces"

C:\temp\tcbugs>echo hi > "dir1 with spaces"\foo.txt

C:\temp\tcbugs>type "dir1 with spaces\foo.txt"
hi

C:\temp\tcbugs>type "dir1 with spaces/foo.txt"
The system cannot find the file specified.

What is particularly interesting about this is that it appears to be specific to the cmd.exe shell and doesn't occur in PowerShell (nor presumably in the win32 API):

PS C:\temp\tcbugs> type 'dir1 with spaces/foo.txt'
hi

Another point of interest is that changing directories with 'cd' and using '/' used as a path separator with cmd.exe does work:

C:\temp\tcbugs>mkdir dir2_no_spaces

C:\temp\tcbugs>cd ./dir2_no_spaces

C:\temp\tcbugs\dir2_no_spaces>cd ..

Yet, I can't find any reference to this particular problem anywhere online nor in MSDN's commonly cited documentation:

Naming Files, Paths, Namespaces

Which leads me to ask: why does this happen, and is there a definitive source which documents this quirk?

UPDATE:

dbenham points out that the problem is present regardless of whether spaces are in a directory name, so removed reference to it in the title and question body. Also added an example of 'cd ./' that works, while other commands don't.

Drawing answered 9/5, 2012 at 20:34 Comment(12)
/ can be used as a path separator at the API level, but you aren't calling the API directly. You're using cmd.exe, and cmd.exe parses the / as a command line option.Heavensent
I suspected as much, but also expected something covering this case would be documented somewhere specifically. The documentation I have found covering path separators--even in the context of the cmd shell--doesn't mention this particular issue so far as I can tell.Drawing
Where is the documentation that says slash can be used as a path separator in cmd.exe?Heavensent
The spaces have nothing to do with the problem. Even if the folder does not have spaces in the name, the forward slash still does not work.Uncalledfor
Raymond--Looking just now, I don't actually see anything mentioned cmd.exe explicitly.Drawing
dbenham--Looks like I'm mistaken about the spaces having anything to do with the problem; will edit the question.Drawing
If you have a top-level directory named 'D', cd /D won’t work...Schwenk
@BrianNixon: Seems like CD works inconsistently with /-delimited paths. If the path starts with a /, CD will say it can't find it (unless you are trying /D, in which case it will complain about the syntax error).Princessprinceton
@AndriyM - CD /TEMP works for me on Vista. CD /D does nothing because of the /D option. Nor does CD "/D" work. But CD C:/D works just fine!Uncalledfor
@dbenham: Thanks. That's "testing when sleepy" for you: for some reason it didn't occur to me to try a name that didn't begin with d. I was using dd in my tests, and I was on XP SP3 at the time, by the way. Now I am on Win7 and I can confirm two things: CD /Temp does work and CD /Danything doesn't seem to. So, thanks again, for reminding me what sensible people are supposed to do anight. :)Princessprinceton
Also note that the type in CMD.EXE and type in PowerShell are not the same command (like some external type.exe). In CMD.EXE it is built-in and in PowerShell it is the Get-Content commandlet. CMD.EXE built-ins parse their arguments sometimes different than external commands do (for example cd.. is the same as cd ..).Cardenas
webpages.charter.net/danrollins/techhelp/0295.HTMUndercoating
U
10

Edited to remove opinion

Whether or not Windows CMD.EXE is supposed to support forward slashes in paths, the fact is sometimes it works, sometimes it doesn't, and sometimes it appears to work but gives the wrong result - AKA a bug.

It's time for some experiments :-)

All tests were run on Vista

C:\>md "c:/temp/"

C:\>REM The forward slash works with MD!

C:\>echo hello world 1>>"c:/temp/test.txt"

C:\>REM Redirection works with forward slashes!

C:\>type "c:\temp\test.txt"
hello world

C:\>REM Of course TYPE works with back slashes

C:\>type "c:/temp/test.txt"
The system cannot find the file specified.

C:\>REM But forward slash version fails

C:\>type "c:/temp\test.txt"
hello world

C:\>REM But TYPE works with forward slash as long as last slash is back slash

C:\>dir "c:/temp/test.txt"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

File Not Found

C:\>REM Note how DIR lists the directory with a \, yet fails to find any files

C:\>dir "c:/temp/*"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

File Not Found

C:\>REM DIR Still fails with forward slashes

C:\>dir "c:/temp/"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

05/09/2012  09:58 PM    <DIR>          .
05/09/2012  09:58 PM    <DIR>          ..
05/09/2012  09:58 PM                13 test.txt
               1 File(s)             13 bytes
               2 Dir(s)  337,001,615,360 bytes free

C:\>REM But forward slash works if no file is specified!

C:\>dir "c:/temp\test.txt"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

05/09/2012  09:58 PM                13 test.txt
               1 File(s)             13 bytes
               0 Dir(s)  337,001,615,360 bytes free

C:\>REM And DIR works with forward slash as long as last slash is back slash


C:\>REM Now add another folder to the path hierarchy

C:\>md "c:/temp/temp/"

C:\>REM Still can create folder using forward slashes

C:\>copy "c:/temp/test.txt" "c:/temp/temp/"
The system cannot find the file specified.
        0 file(s) copied.

C:\>REM Failed to copy with forward slashes

C:\>copy "c:/temp\test.txt" "c:/temp/temp/"
        1 file(s) copied.

C:\>REM But forward slash works if last slash before file name is back slash


C:\>REM Rerun some past tests

C:\>type "c:/temp/test.txt"
The system cannot find the file specified.

C:\>REM Good - it still fails

C:\>dir "c:/temp/test.txt"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

05/09/2012  09:58 PM                13 test.txt
               1 File(s)             13 bytes
               0 Dir(s)  337,001,615,360 bytes free

C:\>REM What is going on?! :( Why did that seem to work now?
C:\>REM More on that later.


C:\>REM Now test the new folder

C:\>type "c:/temp/temp/test.txt"
The system cannot find the file specified.

C:\>REM Forward slashes still fail with TYPE

C:\>type "c:/temp/temp\test.txt"
hello world

C:\>REM But forward slash still works as long as last slash is back slash

C:\>dir "c:/temp/temp/*"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp\temp

File Not Found

C:\>REM Again, forward slashes fail, but directory path is listed properly

C:\>dir "c:/temp/temp/"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp\temp

05/09/2012  09:58 PM    <DIR>          .
05/09/2012  09:58 PM    <DIR>          ..
05/09/2012  09:58 PM                13 test.txt
               1 File(s)             13 bytes
               2 Dir(s)  337,001,615,360 bytes free

C:\>REM And again it works if no file is specified

C:\>dir "c:/temp/temp\test.txt"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp\temp

05/09/2012  09:58 PM                13 test.txt
               1 File(s)             13 bytes
               0 Dir(s)  337,001,615,360 bytes free

C:\>REM Again forward slashes work as long as last slash is back slash

Here is a case that clearly demonstrates a bug.

c:\>dir /s /a-d temp
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

05/10/2012  08:01 AM                13 test.txt
               1 File(s)             13 bytes

 Directory of c:\temp\temp

05/10/2012  07:57 AM                10 test.txt
               1 File(s)             10 bytes

     Total Files Listed:
               2 File(s)             23 bytes
               0 Dir(s)  337,325,191,168 bytes free

c:\>REM Note the different file sizes found in each directory

c:\>dir "c:/temp/test.txt"
 Volume in drive C is OS
 Volume Serial Number is EE2C-5A11

 Directory of c:\temp

05/10/2012  07:57 AM                10 test.txt
               1 File(s)             10 bytes
               0 Dir(s)  337,325,191,168 bytes free

c:\>REM It is listing the wrong file!

One can debate whether Windows CMD is "supposed" to support forward slashes. But that last result is a bug! Even if there is operator error in using a forward slash, Windows should not give that result.

Uncalledfor answered 10/5, 2012 at 2:13 Comment(5)
What’s your basis for describing the behaviour as a bug? (As Raymond Chen asked above, where’s the documentation that states that cmd should accept forward slashes as path separators?) And as Larry Osterman noted, the origin of the use of the forward slash as the option separator might not even be Microsoft’s doing. Would you describe as a “bug” the behaviour of Unix-tradition commands that can’t deal with file names beginning with - without special arrangement?Schwenk
@BrianNixon - I consider it a bug (or design flaw) if a system gives inconsistent results. I'd be perfectly happy if CMD worked with forward slash in paths or didn't, but to sometimes work and other times not is a bug in my book. And my last example in the edited answer clearly demonstrates a bug by any rational definition of "bug" that I can think of. I've removed opinion from the answer and stuck to the facts. But in this comment I will state: "I believe MS attempted to support forward slashes in paths and ended up with a buggy undocumented feature".Uncalledfor
@dbenham: I am almost certain MS didn't attempt to support forward slashes in cmd. They (intentionally) support them in the API, but in cmd it just happens to work when the text is just passed to API and not when it is parsed. The difference between md and type, both being built-in commands, is really curious.Luckett
@JanHudec - I suppose the developers of cmd could have been naive as to the API's interpretation of /, but I doubt it. Either way, they should have been aware and designed accordingly. It should have been a conscious decision to either support / as a path separator in all internal command situations, or else disable it in all cases. That is my opinion anyway. :-) Or at least document that / is unreliable as a path separator and therefore should be avoided.Uncalledfor
@dbenham: It should have been documented. Perhaps it is, somewhere; Microsoft documentation is famous for being difficult to find what you are actually interested in. It couldn't have been supported, because cmd.exe is an NT port of command.com and I don't know whether forward slashes worked back then (DOS was not POSIX compliant, only WinNT and newer are).Luckett
Y
-1

Wie had some strange behaviour with slash to and we traced it down to the fact, that a path with a leading slash isn't seen as an absolute path, so

C:\>cd /temp

C:\temp>rem works we are in the root directory

C:\temp>cd /temp
Das System kann den angegebenen Pfad nicht finden.

C:\temp>rem does't work but

C:\temp>cd \temp

C:\temp>rem \ indicates absolute path

C:\temp>cd ..

C:\>cd /temp

C:\temp> cd /ca

C:\temp\CA>rem qed

Perhaps it explains also the bug stated above - im not clear, at which directory the commands are executed.

Yeryerevan answered 6/6, 2013 at 13:3 Comment(2)
Nice theory, but on my Windows 7 machine I get different behavior. cd /temp works fine for me, treating it as a root folder. But the other bugs I list in my post still apply.Uncalledfor
These are interesting examples, but they don't even begin to address the question of "why".Noncooperation
F
-7

I am not sure why the '/' is working in PS. Back to the history, DOS was based on UNIX and it is a small set of UNIX. In UNIX the path separator is '/', while in DOS it is '\'. I worked on some Windows and DOS apps before. In order to convert some UNIX pattern like commands or path and make sure they are valid DOS command or path, I wrote a small converter to transform '/' to '\' like this:

string fileNameFromWeb;
...
string windowsFile = fileNameFromWeb.repleace("/", @"\");

You may add this feature to tolerant '/' in your app in case of accessing to files in Windows. I guess PS may have this type converter to allow command or path using '/' or '\', or Windows will take '/' in file name.

Fallible answered 9/5, 2012 at 20:45 Comment(6)
Thanks, but what originally led me to this problem was a bug in some third-party software--so that option isn't available to me. Of course, if it were my software I would have simply done something like that and not bothered to ask this question.Drawing
If you're using .NET or Mono, you can use Path.DirectorySeparator instead of hard-coding it. msdn.microsoft.com/en-us/library/…Retake
-1 Sorry, but "DOS was based on UNIX and it is a small set of UNIX.", that has got the be the biggest blasphemy ever! Actually, DOS was somewhat based on CP/M.Cardenas
It works in PS, because it's parsing rules are different and when the string gets unmodified to the API, it works.Luckett
@dwerner: If you are using .NET or Mono, or C++ or anything, you can always use /. cmd.exe is the only (or at least I've never header of any other) part of Windows where forward slashes don't work.Luckett
@JanHudec: There are, of course, quite a number of tools that allow a leading / to introduce command-line options. Thankfully for those of us using bash, most of these also allow -. (Whatever bash you might use on Windows, arguments starting with / will tend to be subject to path translation when invoking programs that it doesn't recognize as fellow *nix ex-pats, so it's generally a lot easier to just use - to introduce options than to fight the path translation.) Presumably you were only referring to non-leading /?Saponin

© 2022 - 2024 — McMap. All rights reserved.