Why does Windows use backslash as path separator? (2019)

(os2museum.com)

72 points | by lproven 9 days ago

12 comments

  • Alupis 9 days ago
    I find these sort of articles so very tiring...

    I realize this is from the OS/2 Museum and not Microsoft - but the result is the same:

    Article written about a poor engineering decision made decades ago, which for reasons that perplex everyone still live-on today. Then the Microsoft apologists come out of the woodwork to explain how easy it is to live with these poor engineering decisions and how smart Microsoft Engineers are, and how it's literally all other operating systems that somehow are lacking, blah blah blah.

    Backwards compatibility is usually the smoke screen apologists deploy during these discussions. As-if in the past few decades Microsoft couldn't have written a simple '\' -> '/' converter... Hell, if you look in the Explorer address bar, Microsoft even hides the path separator - opting to replace it with arrows instead.

    Let's not even start on the CRLF thing...

    Yes, Windows owes it's origin to OS/2, and OS/2 used '\' instead of '/' - so we should never correct a decision inherited from an OS that died 22 years ago...

    • itslennysfault 9 days ago
      As a long time *nix user who briefly worked at Microsoft (and therefore on Windows), I was very happy to learn that Powershell is perfectly happy with forward slashes in paths. If you tab-complete it switches them to backslashes (which is "fine"), but you can type commands using forward slashes without issue. Also common linux commands (ls, cd, mv, cp) all work in Powershell. It really makes the transition painless.
      • Alupis 9 days ago
        I personally have found PowerShell to be obnoxious. It doesn't seem to know what it's supposed to be and tries to be everything all at once. The syntax for commands is super "Microsofty" if you know what I mean.

        I get around by using Git Bash (which is actually quite good for being a bundled afterthought), cygwin, or lately even WSL containers.

        • TiredOfLife 9 days ago
          Git Bash, cygwin, WSL containers are all completely different things. PowerShell is a shell like bash, just with a different syntax.
        • sbelskie 9 days ago
          What different things do you think it is trying to be?
          • therein 9 days ago
            I have nothing against PowerShell. I've used it for avoiding detection etc. in the past. Fun tool that surprises and delights in unexpected ways.

            It is pretty powerful/insane that stuff like this is a part of PowerShell and that's probably what the GP is talking about:

                Add-Type -TypeDefinition @"
                using System;
                namespace DemoCode
                {
                    public class DemoClass
                    {
                        public static void WriteHello()
                        {
                            Console.WriteLine("Hello");
                        }
                    }
                }
                "@
                [DemoCode.DemoClass]::WriteHello()
            
            Or LoadLibrary call and invocation from PowerShell. [0] [1]

            It blurs the lines as to what it is no matter how you look at it.

            In contrast, try doing that in cmd.exe or invoking a function from a shared object after getting a pointer to it using dlopen through a POSIX shell.

            [0] - https://www.powershellgallery.com/packages/PSReflect-Functio...

            [1] - https://fuzzysecurity.com/tutorials/24.html

      • naikrovek 9 days ago
        Windows itself is fine with forward slashes as a path separator, as well, though LOTS of userland Windows applications weren’t aware of this and enforced backslashes themselves.

        Command lines, graphical shells, OS save and open file dialogs do not care if you use slash or backslash, and the Win32 API has never enforced backslashes as a path separator.

        • Dwedit 9 days ago
          You'll be surprised what the Win32 API will accept as a path. You can run 'type \\?\GLOBALROOT\Device\OSDataDevice\Windows\win.ini' at a command prompt, and it will succeed. You can even provide a path like that to MS Paint on the command line, and it will happily open the file. But Shell32 (Windows Explorer and File Load/Save dialogs) won't accept that kind of path.
      • wglb 9 days ago
        This is also true if you e.g. write a C program to create a file whose pathname contains a slash. This is deep within the OS, likely due to posix compatibility
      • Nihilartikel 9 days ago
        I work a lot in powershell, and I want to like it. It is built around good ideas.. but oof, every time I have to special case on a return value being either a list or a single item depending on the result-len==1 or not, I die a little inside.
        • jiggawatts 9 days ago
          $alwaysList = @( Get-Something )
        • ScottEvtuch 9 days ago
          I think there are some tricks to ensure a list in pwsh for these sort of operations. I vaguely recall ending variable assignments with a comma to avoid this.
    • canucker2016 9 days ago
      Windows used many of the MSDOS services, like file system access. Windows was built on top of MSDOS in the beginning.

      Windows predates OS/2 (OS/2 development started in 1985 according to Wikipedia)

      How is it a poor engineering decision?

      What about the original Mac OS using colon as a path separator? Or Lisa OS using the hyphen as a path separator?

      see https://retrocomputing.stackexchange.com/questions/17069/why...

      • Joe_Cool 9 days ago
        Japanese DOS had ¥ as the path separator or more specific at 0x5C. It still causes headache with the MS Mincho font. Japanese users are used to seeing ¥ at the DOS prompt so some Windows Console fonts just replace the backslash.

        Since you never know if it's a backslash or an actual Yen sign. Total fun.

        • Dwedit 9 days ago
          MS Mincho and MS Gothic (and many others including Meiryo) both use the Yen Sign (unicode 0xA5) character graphic for the Backslash character. There are also a few Japanese fonts (such as Sazanami Gothic) that don't do this.

          The separate halfwidth yen sign does not exist in Shift-JIS at all. So any time a non-unicode Japanese Win32 application needs to draw a halfwidth yen sign, it must draw a backslash. And you can't make the official character mapping convert Backslash 0x5C into Yen sign 0xA5, otherwise all file paths would break.

      • TillE 9 days ago
        Yeah I think it's far more interesting to view this as a series of people making probably the best possible decision at the time, and winding up in a slightly unfortunate, suboptimal place.

        That's hardly uncommon! Examine the history of basically anything.

      • naikrovek 9 days ago
        > Microsoft reportedly wanted to use the forward slash as path separator, but IBM nixed the idea because it would have created an incompatibility with DOS 1.x, which already used the forward slash as a switch character, separating command options.

        It isn’t a poor engineering decision, that guy just didn’t read the decision criteria.

        Also, according to spec, CRLF is the proper sequence for a newline, and both Unix and MacOS chose incorrectly.

        • Alupis 9 days ago
          Which spec would that be? It's not the ISO spec, nor POSIX.

          CRLF existed originally because of mechanical typerwriters required two separate actions - Carriage Return (move the carriage back to the start of the line), Line Feed (advance the page to the next line).

          CR is a waste for computing... it literally does nothing beneficial.

          Someone should figure out the climate impact of decades of wasted processing of CR characters... that might motivate people to fix this as well.

          • naikrovek 9 days ago
            > Someone should figure out the climate impact of decades of wasted processing of CR characters... that might motivate people to fix this as well.

            LF vs CRLF is a single molecule of water compared to the seven seas of waste created by Electron apps or even just JavaScript itself. Todays developers are lazy as FUCK and there is no pressure for them to stop being lazy.

            See: https://tonsky.me/blog/js-bloat/

            > CR is a waste for computing... it literally does nothing beneficial.

            When “LF” means “line feed and carriage return” both, as it does thanks to UNIX, yes. On teletype machines “line feed” meant “line feed” and “carriage return” meant “carriage return”. You need both.

            Today we use an LF which means both “CR” and “LF” and we act like CR is the problem, when it was us choosing a single byte to mean two separate things joined together.

            Even as a kid in school in typing class, I used a typewriter with a parallel port (probably serial, really, because you could use the keyboard without putting text on paper), and it could be used to print text sent to it. CR and LF had very different meanings on that typewriter. I wish I remembered what make and model it was…

          • skissane 9 days ago
            > Which spec would that be? It's not the ISO spec, nor POSIX.

            RFC3676, RFC2045, among others. CRLF is the Internet standard newline

            • Alupis 8 days ago
              Which explains it's use in operating systems how exactly?
              • skissane 8 days ago
                How did it become the Internet standard? Because at the time it was adopted as the Internet standard the majority of operating systems used it. Probably the biggest influence on both the Internet standard and Microsoft was DEC. And actually, it is used by Unix too, in the TTY layer: Unix by default translates LF to CRLF on output - and that translation is in the POSIX standard. So the claim that CRLF isn’t in POSIX is false
            • naikrovek 8 days ago
              thank you. I was about to look, but saw this.
          • Const-me 9 days ago
            > CR is a waste for computing... it literally does nothing beneficial

            CR enables to update a line of text. Print some text without newline at the end, print CR, print another line, and the old text will be overwritten with the new one.

            Some command-line apps are using the trick to print progress bars, progress percentage, or similar. This is very beneficial.

            • Alupis 9 days ago
              This is almost always implemented using direct placement of the cursor, not via a literal CR char/command. CR is literally useless, except for being artificially required in some windows text editors.
              • Const-me 9 days ago
                Cursor placement is hard to do portably because every OS has incompatible ways for that. You gonna need SetConsoleCursorPosition on Windows, and multiple versions of these terminal escape codes on Linux.

                printf( "\rsomething " ) is much easier.

          • tracker1 9 days ago
            It's not the same in many terminals... I also think lack of Vertical tabs on keyboards is sometimes a shortcoming.
    • skissane 9 days ago
      > Let's not even start on the CRLF thing...

      CRLF is actually the Internet standard. It wasn't something Microsoft came up with, it was something they inherited from DEC

      > Yes, Windows owes it's origin to OS/2, and OS/2 used '\' instead of '/' - so we should never correct a decision inherited from an OS that died 22 years ago...

      That's not what the article actually says though. DOS 2.0 decided on '\' instead of '/', and both OS/2 and Windows inherited that decision from DOS.

    • mardifoufs 9 days ago
      Why is / better than \ ?
      • Alupis 9 days ago
        For starters, `\` is used for escape sequences for just about everything... meaning you now have to do the `\\` dance everywhere you need to write this path separator.

        Yes, it's true modern languages have things like `Path.separator` and stuff to abstract this away, but you cannot always use them in all contexts.

        It's small friction that adds up to a sore bum after a while...

        • saurik 9 days ago
          FWIW, I have never wanted to put a \ in a filename, but I have often wanted to put a / in a (pretty) filename, as / is used in standard English all the time; I then find myself using "-" instead and that makes me unhappy. I'd much rather have seen ^ as the escape character and \ as the path separator.
          • hollerith 9 days ago
            You can put slashes in filenames in MacOS's Finder app. If you use ls to view the filename, you'll see colons where Finder shows slashes.
            • tracker1 9 days ago
              Want to really mess with someone, do that on a mac file share on a windows server... You won't be able to do anything to that file or directory from Windows. Not sure if it's still an issue, but definitely was in the NT4/Win2k days.
            • saurik 7 days ago
              Yeah, because Mac used to : as the separator... but, : is also an extremely commonly-used character that I have off wanted to put in a filename.
        • Joe_Cool 9 days ago
          The real fun starts with UNC paths. Is it `\\\\server\\share\ with\ space` or `//server/share\ with\ space` or any combination of those, preferably with quotes.
        • jz391 6 days ago
          Could be worse of course: Multics (the first system with hierarchical names) used greater-than (>) as separator. Unix/DOS use of slashes gives us the sane pipeline/redirection syntax we all love (see [1] for the Multics redirection syntax).

          [1] https://retrocomputing.stackexchange.com/questions/7030/why-...

      • OsrsNeedsf2P 9 days ago
        Apart from the fact \ is used as an escape sequence?
    • tracker1 9 days ago
      If you're using anything resembling modern Windows, you can use forward slashes for path separators and it works fine pretty much everywhere.
    • dekhn 9 days ago
      I use forward and backward slash on Windows all the time. I think it's less of a problem of spaces in filenames, which makes a lot of pipe-related stuff harder to do (see find -print0 and xargs -0).
      • asveikau 9 days ago
        Spaces in filenames in the command line on Windows is a horror in part because there is no kernel level equivalent of argv. In the eyes of the Windows kernel, the command line is an unparsed utf-16 string, and it's up to the application or C library to tokenize it. This means there is no standard way to tokenize it. Ultimately, this means there is no standard way to escape a shell command's arguments, as you would need to do for spaces. Most people just put it in double quotes but this is pretty much the honor system.
        • dekhn 9 days ago
          I'm not entirely sure what you're saying is different here.

          I picked the first MSFT page on argv, https://learn.microsoft.com/en-us/cpp/c-language/parsing-c-c... and compiled and ran that program with various command lines, and it does exactly what I expected (argv array members are tokenized according to my quoting).

          Could you be clearer, perhaps by posting a simple C example and a few command lines demonstrating what you mean?

          • asveikau 8 days ago
            Here's an example of someone citing a disagreement between CRT and shell32:

            https://github.com/rust-lang/rust/issues/44650

            This in addition to the Rust CVE mentioned elsewhere in the thread which was rooted in this issue:

            https://blog.rust-lang.org/2024/04/09/cve-2024-24576.html

            Here are some quick programs to test contrasting approaches. I don't have examples of inputs where they parse differently on hand right now, but I know they exist. This was also a problem that was frequently discussed internally when I worked at MSFT.

                #include <stdio.h>
                int main(int argc, char **argv)
                {
                   for (int i=0; i<argc; ++i)
                      puts(argv[i]);
                   return 0;
                }
            
                #pragma comment(lib, "shell32.lib")
                #include <windows.h>
                #include <stdio.h>
                int main()
                {
                   PCWSTR cmdLine = GetCommandLineW();
                   if (cmdLine)
                   {
                      int argc = 0;
                      PWSTR *argv = CommandLineToArgvW(cmdLine, &argc);
                      if (argv)
                      {
                         for (int i=0; i<argc; ++i)
                            printf("%ls\n", argv[i]);
                         LocalFree(argv);
                         return 0;
                      } 
                   }
                   return 1;
                }
        • Const-me 9 days ago
          > it's up to the application or C library to tokenize it

          Technically yes, but practically the only correct way to tokenize these command line strings is CommandLineToArgvW WinAPI implemented by Shell32.dll.

          • jasomill 9 days ago
            This is fine for parsing command line arguments in your own programs, but unhelpful when attempting to provide a mechanism to reliably pass a user-supplied argument list to an arbitrary external program that is free to interpret the string returned by GetCommandLine arbitrarily (so the notion of "passing a list of arguments" isn't even generally applicable).

            cmd.exe is an important and terrible example:

            https://learn.microsoft.com/en-us/windows-server/administrat...

          • asveikau 8 days ago
            Within Microsoft when I was there, it was considered taboo to introduce a dependency to shell32 where it did not already exist. I tried to add a call to CommandLineToArgvW once and it got flagged.

            From the part of Microsoft that was focused on cleaning up the windows code base in that era, the shell was not considered a core component. All of the utility functions that it provides like this were considered baggage, improper layering, poor design.

        • jiggawatts 9 days ago
          Just use PowerShell. It has no issues with spaces anywhere, and uses explicit quoting rules similar to C# and other “proper” languages.
          • asveikau 9 days ago
            If powershell is dispatching to other cmdlets then fine. If it needs to call CreateProcess on a win32 program then the issue I'm talking about definitely exists.

            (I don't personally like powershell but I don't think my gripes with it are really relevant to this thread.)

            • dekhn 9 days ago
              I don't think anybody else here is talking about CreateProcess. We're talking about the shell.
              • asveikau 9 days ago
                This is how a shell works. It works by creating processes.

                On Unix, you create a process with fork() and execve(). Execve takes a list of arguments, already parsed and tokenized. A shell is free to interpret the command line however it likes to build this, but at the syscall level it is completely unambiguous what the parsed array looks like.

                On Windows, you call CreateProcess. This takes the command line as an unparsed string. It is the child process's responsibility to chop it up into argv. This is the source of ambiguity that I'm talking about.

                • dekhn 9 days ago
                  The comment I wrote starting this thread wasn't about command line parsing, it was about pipes, and the need to use a non-space delimiter NULL to pass lists of files that contain spaces.

                  What you're talking about is related, but different. You're saying that Windows forces an unnecessary join and split (with all the complex rules required to properly parse a quoted string) when using the Windows equivalent of exec(). which is inelegant, but unrelated to what I'm describing above (what I describe above differs because of how newlines and spaces are treated as delimiters (IFS)).

                  Further, from the testing I did, there is no noticeable impact on my C application which reads from argv- the C runtime seems to handle this transparently.

                  • asveikau 9 days ago
                    > Further, from the testing I did, there is no noticeable impact on my C application which reads from argv- the C runtime seems to handle this transparently.

                    I disagree with your assessment here.

                    First, the C runtime doesn't have the "part of the system" feel that it does in the Unix world. There is a CRT in the OS, but most programs link to the CRT that ships with visual studio, so it could theoretically change version to version, compiler to compiler.

                    Apart from that a Win32 application could choose to bypass the CRT's entry point and use WinMain(). Many do. Even if it does use CRT main there is GetCommandLine() to reach the raw command line underneath. Shell32 even has a function CommandLineToArgvW which behaves differently from CRT. Those two are different from parsing done by cmd.exe. There is a lot of ambiguity is my point.

        • hun3 9 days ago
    • asveikau 9 days ago
      With respect, what the hell are you talking about?

      Win32 file APIs can actually use either '/' or '\\' as a path separator. The stuff this is talking about is mostly around DOS command line tools and the successor, cmd.exe, which yes is mostly meant to run scripts written for DOS.

      '\\' was selected by DOS, specifically DOS 2.0 per TFA, several years before OS/2 existed.

      • Alupis 9 days ago
        When you open Explorer and click in the address bar - what path separator is displayed? How about when you install software - what path separator does it show?

        > Win32 file APIs can actually use either '/' or '\\' as a path separator.

        Fantastic - so why are we still entertaining this idiotic file separator everywhere within the OS itself?

        > '\\' was selected by DOS, specifically DOS 2.0 per TFA, before OS/2 existed

        Fine - so why the hell are we still doing things like a dead, defunct OS did and literally nobody else did because, you know, it was unintelligent?

        • asveikau 9 days ago
          > Fantastic - so why are we still entertaining this idiotic file separator everywhere within the OS itself?

          Dude, why are you so angry about what direction a slash goes?

          Once they introduced the ability to use either one, they still had a lot of software that hardcoded '\\', including lots of their own. Again, they support either one in most places. The backslash is considered more canonical because it came first.

          Going back to DOS for a second, TFA even says Microsoft wanted to use '/' in DOS 2.0 when they introduced directories (1983), but IBM objected.

          • Alupis 9 days ago
            IBM objected in 1983 - yet that decision lives on today? It's what Windows displays to users, even if you can actually type in / and things still work.

            When Microsoft wrote IIS and other web technologies the internal friction of path separators must have been fun to experience. "Why are we still using \ again, Jim? Oh, that's right, we chose poorly a decade ago and for some reason can't be bothered to fix it!"

            > Dude, why are you so angry about what direction a slash goes?

            Because it's rubbed my bum raw over the years and I've finally had enough! I mostly jest... but seriously, it's super annoying to deal with and a constant reminder of the poor decision making Microsoft products often encompass.

            • foobarian 9 days ago
              You know what happens when you write a \ --> / converter? You get the python2 to python3 migration mess. Except with Windows it would have been millions of mom and pop shops left out in the lurch.
              • Alupis 9 days ago
                No it wouldn't - because Microsoft did write a \ -> / converter and none of this bad stuff happened.

                Microsoft just chooses to still display \ to you in the UI... which is ridiculous and perpetuates \ living on in all user-facing places.

                • foobarian 9 days ago
                  Are we arguing different things? I.e. removing support for \ altogether from anywhere in the OS vs. not showing it in UIs?

                  I personally like the latter but it's a matter of taste I guess :-). It gives me warm and fuzzies to see C:\ D:\ etc. live on.

            • asveikau 9 days ago
              Parsing a URI should not be a straight pass to open(2) [or CreateFile in Windows parlance] to get to the filesystem directly anyway ... Think of the security problems with that, or URIs where they don't actually correspond to filesystem objects. So, IIS already needs to parse the path distinctly. I'm going to say it didn't cause them a lot of trouble.

              Note also that Windows tends to use 16 bit Unicode everywhere, that's probably a bigger thing for IIS than the path separator.

        • nullindividual 9 days ago
          Microsoft was very smart to use the backslash. It lead to unrivaled backwards compatibility.

          Saying it was the wrong choice is simply revisionist history.

          • Alupis 9 days ago
            So, we would lose all backwards compatibility by writing a \ -> / converter? I don't buy this logic at all - in fact, as others have pointed out, Windows will accept both separators these days.

            You are, unintentionally, being the very sort of apologist my post above complained about.

            • naikrovek 9 days ago
              I think you just need to get over whatever is making you angry. Non-POSIX systems exist, dude. It’s ok for things to exist…
              • asveikau 9 days ago
                Tempted to bring in the fact that classic Mac used colons as a path separator.

                As TFA says it wasn't clear yet that unix would be so dominant. Also, a lot of these systems were introducing the concept of directories for the first time in their history. That's how old we're talking. That directories are novel to some people at that point.

            • nullindividual 9 days ago
              Personal attacks are not welcome on HN.

              Microsoft wrote a 'converter'. Terminal, Explorer, and other applications recognize "/" and convert it to "\". If it takes both, it doesn't matter which one is "real".

            • lproven 9 days ago
              > You are, unintentionally, being the very sort of apologist my post above complained about.

              Hint: the post you are replying to is humorous and the tone should be read as sarcastic.

              • nullindividual 8 days ago
                No, it wasn't and no, it shouldn't be read as sarcastic. Microsoft should be praised for the backwards compatibility they enabled. That is a feat rare in operating systems today.
                • lproven 8 days ago
                  All right, but in that case, I must ask you to explain the comment, because it make no sense to me at all.

                  Firstly, the choice of backslash in DOS 2 didn't enable backwards compatibility with anything because nothing prior to DOS 2 used the backslash character for this.

                  Secondly, I do not see any basis to say that somehow MS looked forward in time, at the future, and chose a character unused by any other OS.

                  As early-1980s MS did not have a time machine and thus was not looking forwards, then how did that choice help future compatibility? How was the use of backslash better for Windows for Workgroups 3.11 (because that was the first one with its own VFAT filesystem that didn't just call DOS) and subsequent releases? How was a backslash preferable to anything else?

                  How would using any other character be worse?

                  Would choosing a character used by other OSes not have been _better_ for long term compatibility, aiding source code conversion and porting?

                  I really do not see what you are trying to get at.

                  Incidentally, I entirely agree that its compatibility record is astonishingly good, but I can't see any link from that to the choice of directory delimiter.

                  • nullindividual 8 days ago
                    When one speaks of Microsoft's backwards compatibility, they are referring to within the Microsoft domain of operating systems and APIs. If I can run an application from 1985 on modern day Windows, that is what backwards compat refers to and is quite unrivaled -- remember, the most stable ABI on Linux is Win32.

                    > How was a backslash preferable to anything else?

                    Because it existed prior to Windows 1.0 and beyond application compatibility, you also had to work with user familiarity. Heck, it is annoying enough to swap between macOS and Windows for Ctrl/Cmd-C and Ctrl/Cmd-V, or even within macOS between Mac applications and the Terminal. Or my worst personal enemy, Ctrl-H/Cmd-H (browser History vs. hide window) in a browser. Arg!

                    > Would choosing a character used by other OSes not have been _better_ for long term compatibility, aiding source code conversion and porting?

                    Which OS should they have chosen from? [0] Apple SOS [and all future versions of macOS]? VMS/OpenVMS? RiscOS? Domain/OS? TOPS/20? Stratus VOS? What made SysV or BSD special or 'a clear choice' in path separators in the '80s?

                    > How would using any other character be worse?

                    I don't believe any other character would be better or worse at the time backwards compatibility was ruled supreme at Microsoft. Since their operating systems already used the backslash character, and the preceding mention of user familiarity, and of course the code base is DOS which they probably didn't want to re-write due to effort and cost, they stuck with it.

                    I certainly see a point in changing the path separator if you pulled a Mac OS Classic to Mac OS X style switch, but Microsoft never really did that. Yes, they had NT, but that needed to have compatibility with it's DOS-based sibling as it could also run DOS applications.

                    Oh imagine the threads if they did switch to the forwardslash in Windows... "What else from Linux will Microsoft copy?!" "Did Microsoft switch to the Linux kernel?!". It would make for an exciting day in tech!

                    I'm certainly not against Microsoft changing the path separator to the forwardslash.

                    [0] https://en.wikipedia.org/wiki/Path_(computing)

        • Capricorn2481 9 days ago
          > Fine - so why the hell are we still doing things like a dead, defunct OS did and literally nobody else did because, you know, it was unintelligent?

          Nobody is doing it except the people using cmd.exe over Windows Terminal or Powershell. If you're using a DOS terminal you're gonna get DOS results.

    • naikrovek 9 days ago
      Windows existed before OS/2, though, and MS-DOS (where Windows’ path separator comes from) is of course even older.

      It’s ok to hate Microsoft, but hate them based on facts, and not whatever nonsense you have in mind.

  • PaulHoule 9 days ago
    It's a little known fact that most of Windows works just fine with "/" as a path separator, for instance if you make a system call to open a file or something.

    The major system that won't accept this is cmd.exe so if you are passing parameters to a .bat file that has a filename with a "/" in you will have trouble.

    • coldpie 9 days ago
      Yep. Drives me nuts when I see people fiddling with platform-specific path separators. Just use /, it works everywhere.
      • RedlineTriad 9 days ago
        This sadly isn't quite the case as this post demonstrates[0]

        > - The path is limited to MAX_PATH (260 chars)

        > - Unless you prefix the path with \\?\

        > - However using \\?\ disables automatic conversion of / to \ in the path (and some other normalization)

        See previous discussion[1]

        [0] https://mastodon.gamedev.place/@AshleyGullen/111109299141510...

        [1] https://news.ycombinator.com/item?id=37632232

      • PaulHoule 9 days ago
        I am really in the habit of using pathlib in Python and similar facilities in Java so I just write

          path = HOME / "cards" / f"{card_id}" / "card.yaml"
        • coldpie 9 days ago
          You can do, or you can just skip all the spaces and extra quotes and junk and just use literal /.

              path = f"{HOME}/cards/{card_id}/card.yaml"
          
          Easier to read & write IMO, and works fine. Even on Windows.
          • skinner927 9 days ago
            I really think they goofed Pathlib because of this.

                path = Path(“/foo”) / “a” / “b” / “c”
            
            The following is functionally equivalent to the above:

                path = Path(“/foo”) / “a/b/c”
            
            Which I really think was a mistake. The latter should resolve to “/foo/a\/b\/c” (IMO) because all other invalid characters (like space) are auto-escaped. What’s the point of the overloaded div operator otherwise?
            • glandium 9 days ago
              space is a valid character in paths. / is not. Never.
              • ldjb 9 days ago
                Classic Mac OS used colon (:) as the path separator, so slashes were perfectly acceptable in file and directory names.

                Even in modern versions of macOS, the GUI still allows you to create files and folders with slashes in their names; the slashes get recorded as colons in the filesystem.

      • Zamicol 9 days ago
        It's been years since I've had to work on a Windows system, but I'm suspicious of that. Days of my career at the State of Colorado has been spent fixing / problems. Is this something on newer Windows systems?
        • coldpie 9 days ago
          If you're mucking around with legacy parts of the OS, you might run into troubles. But if you're just doing regular old file I/O from a normal program, nah. Windows doesn't care. You can even mix them.
  • dunham 9 days ago
    The MSDOS 2.0 source code blames IBM:

    Most of these are due to last minute changes to achieve a greater degree of compatibility with IBM's implementation of MS-DOS (PC DOS). This includes the use of "\" instead of "/" as the path separator, and "/" instead of "-" as the switch character.

    https://github.com/microsoft/MS-DOS/blob/80ab2fddfdf30f09f0a...

    • jtotheh 9 days ago
      MS-DOS didn't exist prior to PC-DOS, initially. "IBM's implementation of MS-DOS (PC DOS)" was the gold standard.

      all of it came from QDOS, a CP/M-like OS M$ bought based on hiding their plans, and that IBM made PC-DOS from. PC-DOS shipped with the original IBM PC.

      MS-DOS only became a thing once there were "IBM PC compatible" clones. It was very smart of M$ to see that coming. They kind of rode IBM's coattails into dominance in the market. Back then, personal computers were oddities and when IBM entered the game, their reputation gave them credibility.

  • NayamAmarshe 9 days ago
    Windows has caused us a lot of issues with Upscayl (https://upscayl.org).

    I personally do not use Windows but most of our errors are reported by Windows users where sometimes path parsing is a problem or the drivers mess up vulkan configuration.

    The fact that node takes a different approach to windows paths and sometimes the need to store these paths in storage and re-use them in external spawned processes makes it difficult to work with Windows' different and not so ideal path standards.

    • harles 9 days ago
      > Windows has caused us a lot of issues with Upscayl

      I’d turn that around. Sounds like Upscayl has caused a lot of issues for Windows users. Not developing on and doing little testing on Windows sure sounds like the problem to me.

      • indymike 9 days ago
        First, I love Upscayl. Just used it to make about a decade of early lower resolution digital family photos 90s and early 00s printable and beautiful on HDPI screens. It's fantastic software.

        > Not developing on and doing little testing on Windows sure sounds like the problem to me.

        Most open source developers are not going to switch to "developing on" Windows because of posts like this. Nor should they. Upscayl is on GitHub and would probably appreciate some testing and fixing on Windows.

        As a developer, I don't use Windows at all. When I make cross platform software, dealing with MS-DOS anachronisms isn't interesting or fun. For paid work, yeah, OK I'll do it. But for free stuff, I can see where a developer might not want to put a lot of effort there and focus on the interesting part of their project.

        • Dalewyn 9 days ago
          >But for free stuff, I can see where a developer might not want to put a lot of effort there and focus on the interesting part of their project.

          That's perfectly fine so long as one doesn't claim to be cross-platform (or supports Windows).

          • NayamAmarshe 9 days ago
            but it is cross-platform and supports Windows.

            There might be Windows specific bugs but those are fixed as soon as the community gives feedback.

      • NayamAmarshe 9 days ago
        I'm just saying how Windows increases the development time compared to Linux and Mac when using technologies that utilize Mac/Linux standards.

        Being a cross platform application, Windows gets the same stack but is the cause of more unnecessary issues.

        It is true that we don't have enough testing for Windows but that's because I do not have a Windows machine and Upscayl won't work in a VM so I have to rely on community feedback most of the time.

    • jonathanlydall 9 days ago
      Our desktop product built using Electron and .NET runs cross platform.

      Originally it was on Windows only and I personally did the work required to make it work cross platform once .NET Core became mature enough, so I’m very familiar with the path separator challenges.

      It was a bit of a pain, but not a huge deal. The trick was to just use forward slashes all the time, except for display or storing an absolute path.

      Windows doesn’t seem to care when you use forward slashes for everything even if looks wrong.

      Admittedly the Node code dealing with paths is limited as most of the heavy work in our app is done in a .NET background agent, but there are things like file selection dialogues and config loading that is in the Node part.

      Based on the fact I can’t remember exactly what I did for paths in Node leads me to believe it was pretty much a non-issue, I probably used forward slashes and it just worked.

      It took a lot more work for the .NET aspect where we’re doing a lot more stuff on the file system, I had to find and replace most path usages with a utility function to convert the separators appropriately.

    • lm411 9 days ago
      I'd never heard of Upscayl before. Very impressed!

      Works great on my Mac.

  • garciansmith 9 days ago
    I don't understand the last bit about the Model F Keyboard playing a role. Neither the slash nor backslash keys require shift to be pressed. Unless they just mean that the slash already had another role and therefore the only other free key was the backtick?
  • alkonaut 9 days ago
    > The path separator needed to be a key that does not require Shift to type

    Give these people a Nordic keyboard (it’s Alt+Gr plus one of the keys that is hardest to press while holding Alt+Gr).

    • glandium 9 days ago
      It's AltGr+8 on French keyboards. I think the backslash is not available without modifiers on most keyboard layouts, but US-centrism in decision making was strong back then.
      • Joe_Cool 9 days ago
        I switched to EURKey since I figured I type code more than emails in languages that use umlauts or accents. It takes some getting used to (even more when coming from AZERTY) but it makes me so much more productive. No more cursing at CTRL+] hotkeys.

        It's included in most Linuxes and KDE and the homepage has a download for Windows and Mac as well as a nice keymap: https://eurkey.steffen.bruentjen.eu/

      • euroderf 9 days ago
        On Scando Mac it's Shift-Option-7. Gives new meaning to "three-fingered salute".
  • zabzonk 9 days ago
    > “CP/M got the slash from VMS”, which is simply not possible because CP/M is older than VMS

    surely not - i used cp/m 1.x back in the late 1970s and by that time VMS was a well-developed and sophisticated OS, unlike cp/m which was something you could have knocked up in a week or so.

    • atombender 9 days ago
      According to Wikipedia, CP/M was released in 1974, and VAX/VMS was "announced" in 1977 (presumably means it was available a bit later than that).
    • ewgoforth 9 days ago
      I always thought DOS got the backslash from VAX/VMS, a question which this article seems to avoid asking.
    • InfamousRece 9 days ago
      CP/M was released in 1974 while VMS was around 1977.
      • zabzonk 9 days ago
        you are right. still, i don't think cp/m was used so much until the very late 70s, simply because microcomputers were not used so much until then. and at that time vms was far more powerful. i remember the first time i used vms compared with cp/m on a z80 - no contest.
        • lproven 9 days ago
          > simply because microcomputers were not used so much until then

          Not really, no.

          It's not that they weren't used. It's that they didn't exist yet.

          The first 8-bit microprocessor, the Intel 8008, was 1972. The first chip for which CP/M was developed was the 8080 in 1974. It took a few years for mass availability.

          Given that you got your years badly wrong in your first comment, did you not think "hey I should check this" before commenting again?

  • simonblack 9 days ago
    Because the '/' in MSDOS was already in use as an option-indicator - a carry-over from CP/M

         FORMAT C: /S /U
    
    The option-indicator in UNIX-like systems was the dash/hyphen '-'

         ls -al
    • skissane 9 days ago
      > Because the '/' in MSDOS was already in use as an option-indicator - a carry-over from CP/M

      It wasn't a carry-over from CP/M itself. The utilities shipped with CP/M itself didn't use slash as an option character. PIP put options in square brackets.

      It was a carry-over from Microsoft's programming tools for CP/M. And, as the article points out, Microsoft appears to have borrowed that syntax from DEC TOPS-10, where it originated

    • glandium 9 days ago
      And the article points out it's NOT a carry-over from CP/M.
      • dirkt 9 days ago
        And I am not sure if their argument holds water. CP/M is clearly influenced by DEC usage [1], and various DEC OS and tools had slashes for tool options as a standard. Those then got carried over to CP/M (e.g. PIP), so that was the standard way to define options everyone CP/M used would have known.

        It's really really hard to imagine the usage for slashes as arguments was not a carry over. And for anyone old enough to actually remember the transition from CP/M to MS-DOS (like me), it felt very natural.

        [1] https://en.wikipedia.org/wiki/CP/M

        • fanf2 8 days ago
          As the article explains, CP/M PIP uses [ ] for options, not /
    • lproven 9 days ago
      [Article submitter here]

      > a carry-over from CP/M

      No, it wasn't, and I posted this correcting someone else on HN sharing this disinformation.

      CP/M does not have command switches as standard. There is no standard separator because it didn't support switches. (Some programs did on their own.)

      Didn't you RTFA before posting this -- gods, I hate the term -- fake news?

    • Joe_Cool 9 days ago
      thats why it also works without any spaces

        DIR C:/p/s/w
      
      Doesn't do what you might expect.
  • mholt 9 days ago
    I would just like to take this opportunity to complain about Windows file paths and especially parsing them in cross-platform software like a web server that joins request paths that always use / to Windows filepath roots that may or may not use \. I also hate that Windows paths are limited to 260 characters !?

    Seriously, in Caddy, I have some of the most bizarre special code paths for Windows. For example: https://github.com/caddyserver/caddy/blob/c6eb186064091c79f4...

    Can someone who understands and appreciates the way Windows does files please help me appreciate it too?

    This article did not help me have gratitude for Windows: https://www.fileside.app/blog/2023-03-17_windows-file-paths/

    > we realise that we can construct an almost unlimited number of different path strings that all refer to the same directory.

    :o

    • alkonaut 9 days ago
      Coding with file system paths means accepting just a few difficult facts.

      - a path is not a unique identifier of a file system object. They don’t have canonical names.

      - don’t make any assumptions about case sensitivity, what file names are valid, or what the longest possible path is.

      - avoid baking paths from strings as as much as possible. Use constructs like PathBuf (Rust) that prevent footguns like duplicated or incorrect dir separators. Never use a literal path separator char ‘/‘ or ‘\’ in code is a good rule of thumb.

      • agumonkey 9 days ago
        I remember one article about someone porting code from *nix to windows and having almost no issue due to the author leveraging pathlib. Just a side note.
        • Const-me 9 days ago
          Same applies to C#. The standard library has pretty good APIs for dealing with file names and paths.

          In my experience, a program written in modern .NET 5+ and tested on Windows has a high probability to run flawlessly on Linux, without even a recompilation.

    • tredre3 9 days ago
      The high level Win32 API does this to be helpful because a trailing space is usually not what the user wants. You can argue it's stupid if you want, but the OS supports files that end with dots and spaces just fine if you call the right APIs.

      I guess Go hooks into too high level of an API. But you can prefix all your paths with "\\?\" to "force it" to be evaluated as is.

      Consider the following program:

          package main
          import "os"
          func main() {
             os.Mkdir(os.Args[1], 0777)
          }
      
      Invoking test.exe c:\test... will create c:\test Invoking test.exe \\?\c:\test... will create c:\test...

      See: https://learn.microsoft.com/en-ca/windows/win32/fileio/namin...

      The link also explains why the file path length limit and details how to disable the limit.

    • candiddevmike 9 days ago
      Personally, I don't see the value in building server/tooling software for Windows these days. The market share just isn't there, and it ends up requiring a lot of work and testing to maintain.
      • Dalewyn 9 days ago
        I would peruse such software.

        I can rely on Windows to still be running nice and happy a year later with no attention paid.

        I can rely on Linux to die to a stiff breeze.

        (Note: I'm probably cursed.)

        • lproven 9 days ago
          It's odd. I often hear this, yet I have been professionally supporting Windows in production since version 2.01 in 1988, including deploying NT 3.1, in prod, before any service packs, in 1993.

          It is the direct opposite of 36 years of extensive professional experience.

          Linux is pretty tough. It will run on anything, and can cope with a lot of changes and damage.

          21st century Windows is the most fragile OS I've worked with since classic MacOS.

    • hgyjnbdet 9 days ago
      > I also hate that Windows paths are limited to 260 characters !?

      Easily changed in the registry/ with group policy, though 256 should not be the default today.

      • nullindividual 9 days ago
        MAX_PATH used to be 260 characters but was changed fairly early in Windows 10 life to 32k.

        NTFS has always supported 32k characters in the path with each part being no more than 255 characters.

        Office, OTOH, does not respect/observe MAX_PATH. Do not exceed ~240 characters in the path + filename for an Office document as Office will be unable to open it.

      • jonathanlydall 9 days ago
        Was going to say the situation with path lengths on Windows is mostly gone today, but it does still pop up on the odd occasion.

        For example the built in .zip file support can’t extract long paths (7-zip however has no issue).

        Also my Git client of choice (TortoiseGit) doesn’t fully handle long paths.

        But day to day long paths on Windows is fortunately not really an issue any more and they’ve been steadily improving support over the years.

        Despite generally being a fan of Windows, before Windows 10 the long path situation was infuriating, they even had a blog post acknowledging it’s a problem, but also stating it was going to be very non trivial to fix and as such they didn’t have any particular plans to fix it.

        I suspect that WSL made the limitation more regularly painful enough that they could convince managers that it’s something that had to get fixed.

        Windows Terminal was probably also motivated by WSL.

      • mkoubaa 9 days ago
        Can you assume your users do that?
        • smegsicle 9 days ago
          if they installed windows they knew exactly what they were signing up for
    • Atomskun 9 days ago
      How in the world is your rant in linked file supposed to work?

      * It seems you decide whether to execute a file by its extension, e.g. `.php`

      * You are complaining that Windows is stripping away spaces, so `.php ` becomes `.php`

      * And supposedly this could lead the file being served as static text if you didn't have a Windows workaround?

      It rather seems to me that POSIX accepting `.php ` as a filename, and this not being picked up by a `.php` check is problematic here.

  • ape4 9 days ago
    One of the many problems is the need to escape it in C/C++ code - like

        LPSTR path = "C:\\Program Files";
    
    They really should fix it. Better late than never.
  • jtotheh 9 days ago
    I've seen some discussion of this, I believe that DOS got some ideas from a DEC OS (not VMS) that they were familiar with from using PDP-10s. Or something like that. Also, they had started using forward slashes to signify options to commands. Although I was a card-carrying Linux stan and Windows hater, starting with NT they have done a good job, overall. M$ makes backward compatibility a priority, and thus will not dump bad ideas that have become entrenched. I do think Jobs was right that M$ has "no taste". I am helping teach Intro to CS to HS students (ironically, through a M$ program) and even the teacher did not know why the C: drive is the letter that it is. AFAICT we're all condemned to live with choices made in a cheap clone of CP/M.... Of course other technologies have their bad choices as well (UNIX/C null-terminated strings, maybe, for instance?)
    • bena 9 days ago
      It's C: because A: and B: were already taken by your main drives, your floppy disks.
      • jtotheh 9 days ago
        I know, but when did you last see a floppy disk?
        • bugfix 9 days ago
          What would be the benefits of changing it now? Change for the sake of change would only break backwards compatibility.
          • jtotheh 9 days ago
            UNIX etc has all file access start from /. DOS/Windows has separate trees starting with different letters. I think having it all in one tree structure has some advantages. All paths can be expressed as relative paths, for instance.
            • Joe_Cool 9 days ago
              Windows kind of does have that. They call it the global catalog or Win32 Device Namespaces.

              somehow C: is easier to type than \\?\GLOBALROOT\Device\HarddiskVolume2\ or \\?\GLOBALROOT\Device\Harddisk0\Partition2\ or even \\?\Volume{1ab2d2f9-230f-4c63-bc25-163c085334df}\ though.

            • wglb 9 days ago
              VMS also has separate trees for different logical volumes.
            • somat 9 days ago
              I think having one tree is a huge advantage. take the windows registry, on paper it sounds like a great idea. "lets make a single unified database to hold all config values" In reality, it sort of sucks. One of the reasons it is so unpleasant to use. Is that now you have another tree with different special access patterns and programs that are incompatible with your main tree(or trees in the case of windows).

              I really like the plan 9 ethos here, which can be summed up as "does it vaguely look like a tree? if yes, put it in the file system". My favorite one was html "Hmmm... An html document is tree structured.... hey guys lets make our web browser a filesystem driver. (enthusiastic clapping)". Having said that, having no mainstream browser on plan9 is what usually keeps me from using it. I keep telling myself that avoiding the web drivel that requires a mainstream browser would make me a happier person, but I keep coming back for more.

              • lproven 9 days ago
                > I really like the plan 9 ethos here

                Well, me too, but it is 2024 and we have half a dozen technologies that let us put a few terabytes of non-volatile directly-accessible memory on the CPU memory bus.

                Isn't it maybe time we relegated the technology of sequentially-accessed disk storage -- including SSD -- to legacy status, like tape drives, and stopped thinking about files and folders at all?

                We are one quarter of the way through the 21st century. "Disk drives", including flash memory pretending to be disks, is legacy tech. We do not need filesystems any more. Let's move on and banish this to VMs holding legacy OSes for backwards compatibility with existing workloads.

                • somat 8 days ago
                  A "filesystem" is really just a key:value store, in the unix system the key is hierarchical and each value can have more than one key. The real unix innovation was to combine all such stores present on a system into one tree. The point is to have a nice human accessible address to get your data at.

                  Now, theoretically, all memory access on the system could be done via one simple api. and as plan9 showed most IO can be done via that same api. It is sort of like having all networks be IP or all protocols be HTTP. The implementation may not be ideal but having that narrow waist is a huge quality of life improvement.

                  Realistically, it is only used for items that need to persist outside of a processes run cycle.

                  • lproven 6 days ago
                    There are useful simplifications, and over simplifications.

                    As in a cartoon I once saw: two cats are talking, and one says of the human they're looking at: "it's a box of electronics, and when he presses buttons on the front, it flashes little coloured lights on that panel at him. It keeps him occupied for hours."

                    It's true and 100% accurate, but it's not at all precise.

                    It doesn't matter what kind of store it is. What matters is that it is an indirection mechanism designed for computers which were unable to access large amounts of directly-addressible non-volatile store.

                    Computers no longer suffer from this restriction, but all current OSes are built around this abstraction, and it cripples them.

        • tredre3 9 days ago
          You can set your main drive to the letter A or B, if it truly bothers you.
          • paulmooreparks 9 days ago
            Of course, if you do, be prepared for a lot of software to break because it's hard-coded to use "C:" and not actually use the APIs or environment variables to find the system drive location, user files location, etc.

            A lot of what gets blamed on Microsoft is really down to poor third-party software. Microsoft goes to extremes to keep that stuff running.

    • pixelesque 9 days ago
      The article mentions your first few sentences...

      In the early DOS days, you didn't always have hard drives, but you'd always have floppy disks to boot from, and those letters were used first alphabetically.

    • doublepg23 9 days ago
      I’d be all for a GoboLinux revolution but it seems unlikely from a “if it ain’t broke…” POV.
    • lproven 9 days ago
      > I've seen some discussion of this

      Look, this is not a personal attack, but the reason I posted the link was that it answers the question... and your comment seems to indicate you didn't read it before commenting.

      So why comment at all then?

      And did you not think "hey, if I comment without reading and immediately indulge in speculation I will make it plain to everyone that I didn't read it and I am just guessing"?