Since when does Windows support forward slash as path separator?(retrocomputing.stackexchange.com)
retrocomputing.stackexchange.com
Since when does Windows support forward slash as path separator?
https://retrocomputing.stackexchange.com/questions/28344/since-when-does-windows-support-forward-slash-as-path-separator
71 comments
Heh, I was one of those purists! I do still prefer using `File.pathSeparator` but I fully concede that it is a useless and unneeded abstraction so my preference is likely purely religious.
All in all, I think the Java world suffers majorly from that extreme abstractions. Never in my life have I worked in a language/ecosystem with more (and often unnecessary) abstractions than in Java. Pretty good language overall, but the culture could really benefit from some good old fashioned pragmatism
All in all, I think the Java world suffers majorly from that extreme abstractions. Never in my life have I worked in a language/ecosystem with more (and often unnecessary) abstractions than in Java. Pretty good language overall, but the culture could really benefit from some good old fashioned pragmatism
The Path api will choose the right separator for you. Thinking about it really is a non-concern nowadays.
Yeah, usually I don't bother with manually inserting separators and instead use Path.join or whatever else. It'll do the right thing on basically all platforms.
They still have a point, though. There are virtually no platforms that don’t support forward slashes, yet there are abstractions in place to avoid simply using slashes. This may be irrelevant, but it’s still a useless layer of complexity.
It is not a useless layer of complexity. Encapsulating paths in an object isn’t purely about slashes.
I generally don't like to treat paths as strings just like I don't like to treat pointers as memory addresses. But hey, you don't always have to care about that stuff to make a functioning piece of software. You know, pick your battles, or however the saying goes.
(Not intended to be sarcastic, just in case it comes off that way. I only add the "useless layer of complexity" because it makes the intention more explicit for me.)
(Not intended to be sarcastic, just in case it comes off that way. I only add the "useless layer of complexity" because it makes the intention more explicit for me.)
For what it's worth, .NET Core has the same capabilities of abstracting away pathname separators, if one wants it. Personally, I don't regard such things as useless and unneeded; because I see the value in not writing programs that break what has been a well-known piece of computer lore for 4 decades: namely that one can be Unix-like to a degree on non-Unix platforms such as MS-DOS, DOS+Windows, OS/2, and Windows NT.
According to this post[0] (though I never tested it), sometimes, when using long paths, Windows will disable the forward/backwards slash normalization.
[0] https://news.ycombinator.com/item?id=37632232
[0] https://news.ycombinator.com/item?id=37632232
According to [1], Mac supports using slashes as part of folder names (they use colons instead). So there might be some circumstances where that decision comes back to bite you, if you ever port to Mac.
[1]https://discussions.apple.com/thread/677339?sortBy=best
[1]https://discussions.apple.com/thread/677339?sortBy=best
Oh it's even weirder than that: whether or not paths are separated by colons or slashes is specific to the app you're using, even in modern macOS versions.
To see this in action, open a terminal, type:
I'm not sure which is the native representation, but I do know that every API I've used to interact with the filesystem on macOS has used slashes as the path separator, so GP should be fine. But it's definitely a fun party trick to pull out around unsuspecting Mac users.
To see this in action, open a terminal, type:
touch test:file.txt
Then open Finder and browse to whatever folder you were in and you'll see a file called test/file.txt.I'm not sure which is the native representation, but I do know that every API I've used to interact with the filesystem on macOS has used slashes as the path separator, so GP should be fine. But it's definitely a fun party trick to pull out around unsuspecting Mac users.
They used colon instead, back in pre OS X days. That’s >20 years ago. Admittedly some obscure cases carried that over and remain but you’ll rarely come across them today.
Heh, memory is foggy but I think one colleague occasionally ran it on his Mac without issues. I guess your linked thread is good advice, just dont't do it – like using spaces in filenames sooner or later makes a random shell script go haywire.
yes, if by 'mac' you mean macos 9 or earlier, which was a consideration when java was designed but generally not anymore
My main gripe is "windows-aware" joinPath implementations which try to be helpful and use backslash as path separators when running on Windows (which then might be removed by other code which assumes that backslash is an escape-character). Just use forward slashes everywhere, it's fine and always has been fine since at least the mid-90s.
At risk of picking nits, I feel like if the output of a joinPath call is being used somewhere where escapes can be interpreted at all, something that has nothing to do with your choice of path separator is very wrong.
A common problem is building a command line with paths created with such a Windows-aware joinPath function and then executing that command line.
If that execution is handled by a shell instead of going directly through an operating system's CreateProcess() function, then the command line string may be mangled either by the shell, or some other "helpful" code sitting inbetween which tries to resolve backslash-escapes (which are usually needed in front of quotation marks).
It a very typical problem in cross-platform Python code, and I think I also stumbled over it in Node.js.
If that execution is handled by a shell instead of going directly through an operating system's CreateProcess() function, then the command line string may be mangled either by the shell, or some other "helpful" code sitting inbetween which tries to resolve backslash-escapes (which are usually needed in front of quotation marks).
It a very typical problem in cross-platform Python code, and I think I also stumbled over it in Node.js.
That sounds like an RCE waiting to happen.
The canonical way to solve this would be to pass the components of that command line through a function that escapes or quotes anything that needs to be escaped. In Ruby and when using bash for example we have [0].
Does Windows have something similar?
[0]: https://ruby-doc.org/stdlib-2.5.1/libdoc/shellwords/rdoc/She...
The canonical way to solve this would be to pass the components of that command line through a function that escapes or quotes anything that needs to be escaped. In Ruby and when using bash for example we have [0].
Does Windows have something similar?
[0]: https://ruby-doc.org/stdlib-2.5.1/libdoc/shellwords/rdoc/She...
Another interesting thing about Windows CMD:for most of internal commands, you can omit the space between the command and switch that starts with a slash (a common thing in Windows).
E.g. the following two are the same:
Edit: oh, another more famous example is the equivalence of
E.g. the following two are the same:
ipconfig/all
ipconfig /all
I always wonder how exactly this is implemented (and why?!).Edit: oh, another more famous example is the equivalence of
cd..
cd ..
And I have to admit I still do `ls..` from time to time, since I used Windows first (and most).As the author of a CMD replacement long ago, I remember Rex Conn's comments on how the command-line parser of COMMAND (and hence CMD) was quite arbitrary.
What was implemented, though, was a set of characters that acted as separators between the command name and the rest of the command tail. To many people's surprise in years gone by, this included not just whitespace but things like forward slashes and equals signs and commas. If memory serves, there was even an undocumented NLSFUNC table for looking them up, although my memory might be mis-serving me here.
So one could, for example, treat the COMMAND command line as if it were CONFIG.SYS and do SOMETHING=ARGUMENTS, which was particularly useful for the built-in PATH and DPATH commands.
MS/PC/DR-DOS, and indeed OS/2, programs were passed not a set of arguments but a single command tail, limited to 126 characters on MS/PC/DR-DOS and limited to 64KiB for the whole command-tail(s)-plus-environment-strings on OS/2. (It was the runtime libraries of programs written in programming languages such as C that did of all of the fakery that pretended that there was an argv[], and notably there were slight disagreements between Microsoft, Borland, and Watcom on the wild edge cases.) Usually, the first character of this command tail was the whitespace separator character that got entered by the user. But it didn't have to be.
What was implemented, though, was a set of characters that acted as separators between the command name and the rest of the command tail. To many people's surprise in years gone by, this included not just whitespace but things like forward slashes and equals signs and commas. If memory serves, there was even an undocumented NLSFUNC table for looking them up, although my memory might be mis-serving me here.
So one could, for example, treat the COMMAND command line as if it were CONFIG.SYS and do SOMETHING=ARGUMENTS, which was particularly useful for the built-in PATH and DPATH commands.
MS/PC/DR-DOS, and indeed OS/2, programs were passed not a set of arguments but a single command tail, limited to 126 characters on MS/PC/DR-DOS and limited to 64KiB for the whole command-tail(s)-plus-environment-strings on OS/2. (It was the runtime libraries of programs written in programming languages such as C that did of all of the fakery that pretended that there was an argv[], and notably there were slight disagreements between Microsoft, Borland, and Watcom on the wild edge cases.) Usually, the first character of this command tail was the whitespace separator character that got entered by the user. But it didn't have to be.
[deleted]
I guess only M$ can answer such question. My best guess would be that slashes are not allowed in file names and thus can be treated as delimiter and thus the cmd can actually try to interpret the part before the slash as the command and execute it.
CreateFile and friends will indeed treat "/" and "\" the same, it's even documented that way these days. Except if you are ever in a corner and need to prepend the path with "\\?\" to get around other limitations.
For a while, I think it was the only supported way to have paths longer than 260 characters, so I've seen some high level APIs add it to the path to work around issues (C# used to do this in some paths, not sure if it still will).
It might be rare, but as someone that's had to debug a "why doesn't c:/whatever/data.dat work but c:\whatever\data.dat does?" issue, I err on using the correct file separator.
For a while, I think it was the only supported way to have paths longer than 260 characters, so I've seen some high level APIs add it to the path to work around issues (C# used to do this in some paths, not sure if it still will).
It might be rare, but as someone that's had to debug a "why doesn't c:/whatever/data.dat work but c:\whatever\data.dat does?" issue, I err on using the correct file separator.
[deleted]
Yes, it has worked for ages.
the fact that CMD.EXE (or COMMAND.COM in earlier versions) famously did (and still does) NOT support it has many people confused.
the fact that CMD.EXE (or COMMAND.COM in earlier versions) famously did (and still does) NOT support it has many people confused.
> the fact that CMD.EXE (or COMMAND.COM in earlier versions) famously did (and still does) NOT support it has many people confused.
CMD.EXE does support forward slash paths. But some of its commands you have to quote a path containing forward slashes, or else it will think it is an option character.
For example, `type c:/windows/win.ini` will give a syntax error. But `type "c:/windows/win.ini"` will do what you expect. By contrast, `cd c:/windows` just works.
COMMAND.COM is a different story, in part because unlike CMD.EXE, COMMAND.COM doesn't support quoting of paths. Although, while CMD.EXE is fine with `cd c:/windows`, COMMAND.COM rejects it.
[0] Amazing that win.ini is still there after all these years, but it is just a vestige for 16-bit app support–although still present on 64-bit systems that don't support 16-bit apps.
CMD.EXE does support forward slash paths. But some of its commands you have to quote a path containing forward slashes, or else it will think it is an option character.
For example, `type c:/windows/win.ini` will give a syntax error. But `type "c:/windows/win.ini"` will do what you expect. By contrast, `cd c:/windows` just works.
COMMAND.COM is a different story, in part because unlike CMD.EXE, COMMAND.COM doesn't support quoting of paths. Although, while CMD.EXE is fine with `cd c:/windows`, COMMAND.COM rejects it.
[0] Amazing that win.ini is still there after all these years, but it is just a vestige for 16-bit app support–although still present on 64-bit systems that don't support 16-bit apps.
Since MS-DOS 2.0 :)
The exact answer is more like
> Newer Windows Versions (NT and later) copied that behaviour > Windows applications did not always follow and may or may not accept either when parsing for filenames.
Meaning it _may_ work but it also may not.
> Newer Windows Versions (NT and later) copied that behaviour > Windows applications did not always follow and may or may not accept either when parsing for filenames.
Meaning it _may_ work but it also may not.
> Meaning it _may_ work but it also may not.
The Windows API has always supported forward slash, going back to Windows 3.x, probably even back to 1.x and 2.x. For example, if you run NOTEPAD.EXE in Windows 3.1 [0], and type a path like c:/windows into the File>Open dialog box, it is accepted just as c:\windows would be
However, COMMAND.COM doesn't support forward slash, because of its use as an option character. (Unless you used the undocumented SWITCHAR setting to change the option character to a dash/hyphen, but that setting was disabled in DOS 3 onwards.) CMD.EXE partially has the same problem, although it can be worked around with quoting, which COMMAND.COM doesn't support.
Applications have always been a mixed bag though – including under that label Microsoft products, and even utilities included with DOS/Windows. Although, nowadays it is rare to find applications with that problem, but I'm sure if you go back far enough it would have been much more common. The explosion in popularity of the web and also of Linux and macOS has made Windows app developers (and even users) much more forward-slash-aware than they used to be.
[0] https://www.pcjs.org/software/pcx86/sys/windows/3.10/
The Windows API has always supported forward slash, going back to Windows 3.x, probably even back to 1.x and 2.x. For example, if you run NOTEPAD.EXE in Windows 3.1 [0], and type a path like c:/windows into the File>Open dialog box, it is accepted just as c:\windows would be
However, COMMAND.COM doesn't support forward slash, because of its use as an option character. (Unless you used the undocumented SWITCHAR setting to change the option character to a dash/hyphen, but that setting was disabled in DOS 3 onwards.) CMD.EXE partially has the same problem, although it can be worked around with quoting, which COMMAND.COM doesn't support.
Applications have always been a mixed bag though – including under that label Microsoft products, and even utilities included with DOS/Windows. Although, nowadays it is rare to find applications with that problem, but I'm sure if you go back far enough it would have been much more common. The explosion in popularity of the web and also of Linux and macOS has made Windows app developers (and even users) much more forward-slash-aware than they used to be.
[0] https://www.pcjs.org/software/pcx86/sys/windows/3.10/
There are two answers saying that, and one is sourced to Wikipedia whilst the other has screenshots of tests being run. Just copying Wikipedia to Stack Exchange isn't a good idea in general. In any case, there are plenty of contemporary 1980s discussions of SWITCHAR in CONFIG.SYS to be had, that go over the pathname separator characters as well. This has been well-known as a semi-official thing for 4 decades.
Heck, one could even cite Peter Norton on the pathname separators, writing the The dissection of DOS 3.0 article in his column in the 1984-10-30 edition (volume 3 number 21) of PC magazine.
Heck, one could even cite Peter Norton on the pathname separators, writing the The dissection of DOS 3.0 article in his column in the 1984-10-30 edition (volume 3 number 21) of PC magazine.
That's basically the story of every file name rule on Windows :)
Since the '90s. While the preferred form is '\', '/' was allowed as an alternate path separator.
I just wish that Linux would be less obnoxious about file separators and especially line endings.
Windows mostly just eats linux-style line endings and file paths without a problem, and MOST programs do not have a problem either.
Feed a windows-style path or line ending to linux? Watch how it dies with absurd errors.
Feed a windows-style path or line ending to linux? Watch how it dies with absurd errors.
But \ is a valid character for a filename in Linux. It can't also be a separator.
And, should you check such a file into a git repo, you won't be able to clone it on Windows. With that in mind I would encourage never doing so (and makes me wish git had a filter to prevent it in the first place or at least provide a stern warning.)
i only recently noticed that powershell accepts ~ as a shortcut for your user folder. anyone know how long that had been a thing?
Since 1.0, but it’s PowerShell specific.
PowerShell's ~ can be counterintuitive, as it's relative to the current location's path and defined by a property of the current location's PSProvider:
PS C:\> Get-PSDrive C,S,HKLM | select Name,{$_.Provider.Name},{$_.Provider.Home}
Name $_.Provider.Name $_.Provider.Home
---- ---------------- ----------------
C FileSystem C:\Users\jtm
S FileSystem C:\Users\jtm
HKLM Registry
PS C:\Users\jtm> Get-PSDrive C,S,HKCU,HKLM | select Name,{$_.Provider.Name},{$_.Provider.Home}
Name $_.Provider.Name $_.Provider.Home
---- ---------------- ----------------
C FileSystem C:\Users\jtm
S FileSystem C:\Users\jtm
HKCU Registry
HKLM Registry
PS C:\Users\jtm> cd HKLM:
PS HKLM:\> cd ~
Set-Location: Home location for this provider is not set. To set the home location, call "(get-psprovider 'Registry').Home = 'path'".
PS HKLM:\> (Get-Location).Provider.Home = 'C:\Program Files\Microsoft Office'
PS HKLM:\> cd ~
PS C:\Program Files\Microsoft Office> (Get-Location).Provider.Home = 'HKLM:\SYSTEM\CurrentControlSet'
PS C:\Program Files\Microsoft Office> cd S:
PS S:\> cd ~
PS HKLM:\SYSTEM\CurrentControlSet> (Get-Location).Provider.Home = '..'
PS HKLM:\SYSTEM\CurrentControlSet> cd ~
PS HKLM:\SYSTEM> cd ~
PS HKLM:\> Get-PSDrive C,S,HKCU,HKLM | select Name,{$_.Provider.Name},{$_.Provider.Home}
Name $_.Provider.Name $_.Provider.Home
---- ---------------- ----------------
C FileSystem HKLM:\SYSTEM\CurrentControlSet
S FileSystem HKLM:\SYSTEM\CurrentControlSet
HKCU Registry ..
HKLM Registry ..
PS HKLM:\>In cmd you still have the very intuitive %USERPROFILE%. It can be shortened by a custom environment variable if you own the box.
Even in the Unix world, it's shell-specific, but most shells tend to expand ~ out to $HOME (which in turn gets expanded to the actual path). They also have complicated rules about when ~ characters are expanded or not.
Always did? In code. Not in shells.
FwarkALark(3)
More than ten years later and I still think it was the right choice.