815 comments

[ 2.9 ms ] story [ 330 ms ] thread
Honestly, this still causes a lot of problems with some Software. I've had friends asking for help with obscure errors that were ultimately caused by the files they were using being on a path that contains a space or special character.
I never put spaces, and won't go over 32 characters, preferably less than than 16. even when sending a file to my grand mom. that's how deep rooted the trauma is. and yes, it remains an issue with some parsers and what not.
I still find files on the internet that my browser can't download because too many characters :(.

Edit: can't save, downloading works.

This is a Windows-only issue AFAIK. It's the same reason why people decide to put their projects in something like C:\dev

Apparently it's quite easy to reach the 260 chars limit

No, it's also a Linux issue.
Too many characters on Linux? Quite difficult to reach to be fair. Do you have an example?
I have been trying to repro with a small nodejs server but either the server cut off the content-disposition filename or firefox truncates it. When I get that in the wild I'll post an update.

In the meantime:

    $ touch 1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111
    touch: impossible de faire un touch '1111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111111': Nom de fichier trop long
https://serverfault.com/questions/9546/filename-length-limit... 255 bytes it is then.

Firefox cut off at ~217, httpie at 255.

But it's _per file name_. The path could be waaay longer than Windows' one
Ah, my bad. I thought we were still talking filenames, not paths.
Probably my mistake. You only discussed about file names and I threw in the path thing :)
ascii, no spaces for me

i still get issues with old one-off scripts, that still work, and I forgot to properly quote stuff... plus the urls are pain in the ass with the %20;s.

[0-9A-Za-z_-]+ for me.
Same here and most of the time it's even just [0-9a-z_]+ It's simple and there are no suprises around the corner
Slightly off topic but I find myself stuck at being "please for the love of god don't use spaces in git branch names" old. Anno dazumal this might not even have been an issue and I'm just cargo culting.
And on that topic, git branches are case sensitive but windows filesystem API isn't. Git branches are materialized on the filesystem as files and directories.
If people actually abuse git branches being CS, odds are good they're also abusing CS in the repository content.

The linux kernel is one of the offenders, if you check it out on Windows or macOS (which supports CS but remains CI by default) you'll immediately get garbage in netfilter, because it's an habitual user of having different files with names identical but for the casing e.g. xt_TCPMSS.h and xt_tcpmss.h.

The Windows filesystem API supports CS file- and directory names just fine.

It can be enabled on a per-directory basis like so:

> fsutil.exe file setCaseSensitiveInfo C:\folder enable

NTFS had support for this for decades now - it was designed that way to be POSIX-compliant.

It's shoddy software that lacks support for it, not the OS or the file system.

I enjoy choosing fun branch names from time to time. A few of them: Russian when a user reported a typo in a Russian translation; emoji (mostly added emoji rather than pure emoji); and my personal favourite, a ~250 character diatribe about a single-character bug I was fixing (~250 after I discovered that Git’s error messages when you cause it to try to use file names too long for the file system are fairly mediocre).
Spaces breaking tab completion is still an issue, so, yeah.

ETA: not broken in a technical sense, but having to escape them isn't the best experience. So it's just easier for me to avoid spaces.

Where? It works fine in bash and I think most shells ….
That was a bit of hyperbole on my end, my bad. But you do have to escape the space, which I'm counting as a minor break.
I have had a huge music library on my RAID, and naturally it had a lot of spaces, and non-ASCII, in the file names.

It's cumbersome-ish, but can be made to work.

Then there's shell injection via files containing a newline character in their name...

I must be nightmare customer, because I've always been exploiting my ability to use filenames in full UTF-8. I'm that guy that sends .pdf to your website.
I saw this and felt old, but then the comments in here made me realize that the fear\ is%20real.
There was a Discussion yesterday at work about allowing quotation marks and semicolons in some user-set titles. We use Mongo. But I empathize.
Spaces in file names are a nightmare in Makefiles.
Not if you are careful (a bit like "$@" vs $@ in shell scripts).

Edit: replace $@ with quoted version which actually changes the behavior (I was wrong that the difference is between $* and $@).

I don’t think it’s fair to claim that any Make implementation supports spaces: there are too many fundamental bugs and breakages, so that lots of rather important Make functionality is off-limits if any of your file names will have spaces.

https://www.cmcrossroads.com/article/gnu-make-meets-file-nam... explains the situation in GNU Make in 2007 (and I don’t think it’s changed since then, though jgrahamc especially could correct me). Not being able to use such features as $^ and $(patsubst) is severely debilitating for all but the simplest of makefiles.

That's a fair point, thanks!
All because we use programmatically interfaces that were intended for humans to write: command line, sql, html, email headers.
It's worse than that. Whitespace is a hellish invention in the world of computers: there are multiple characters that may or may not render as whitespace with no way to distinguish them by just looking at the output.

Yet to the machine (script, shell, program, ...) it matters a lot, since u0020≠u0009≠u00A0≠u2000≠u2001, etc. whereas the aforementioned codepoints render like this: " " (and yes, that's indeed the five codepoint in that order - at least I typed them that way).

(Ab)Using whitespace like that can lead to all sorts of funny business, not just when dealing with shell scripts and variable expansion.

Why stop at spaces?

An old prof of mine used to send emails where the subject line was always a valid identifier in C.

Hello_dear_students_where_are_your_reports_

That identifier is clearly too long.

MISRA C:2004, 5.1 - Identifiers (internal and external) shall not rely on the significance of more than 31 character.

I'm hardly afraid but I just think it's poor ergonomics. Same as the move from

   xset m 0 0
to

    xinput --set-prop 'pointer:Logitech USB Receiver' 'libinput Accel Profile Enabled' 0, 1
Everything seems to be going this way in Linux land. Longer names, harder to type names, camelcase names, spaces... I'm looking forward to an OS that treats command line ergonomics as a first class feature and where camelcase & spaces are verboten.
I find this attitude misguided. More descriptive names are more ergonomic for things you only use rarely but they need to be combined with much better autocompletion than most shells provide by default.
You state that as if that were objective.. but that's not my subjective experience at all. Somehow I have a hard time remembering these long names, (is it --conf or --config or --config-file or --config-path? -c would've done it for me. --set or --set-prop or --set-property or --prop or --property?), and I need to look them up in a man page anyway, and I make more typos typing them, and shell completion rarely works well if at all. I also find it harder to read and edit long lines that wrap.

Somehow these short letters stick much better for me, and the effort for finding them in the manual is the same, although in case of extra complexity as with xinput, it's even worse with the long names. I don't use either command often, but it's hard to forget xset m. The only thing I remember about xinput is that it's a horribly long lithany of things which I need to look up every time, and the syntax still feels weird.

the most used options for properly written tools have both short single char option like -c and long-form version --config if you need verbose self-describing option.

If you are using cli tools of github written by a random person, then no wonder you will see non-standard approaches to UX.

PowerShell takes an interesting approach in that it accepts any truncated variant of a long-form flag as a short form, provided it isn't ambiguous (i.e. if the interpreter can't decide which long-form flag to expand a short-form flag to.)

For example, if a command features a "-ConfigFile" flag, valid short-form variants include "-C", "-Co", "-Con", "-Conf", and so on. But if the command featured an additional flag "-ConfigURL" for example, the aforementioned short-form flags would be ambiguous.

getopt_long (and thus most GNU programs) work this way. I think it's probably a misfeature though since it means that adding a new option can introduce ambiguity. Having both short (ex. -x) and long (ex. --exclude) options is a less problematic solution.
The shell ought to be able to help with that. There's no need to remember if it's --conf or --config if you can press --conf<tab>.

One of the things I like about Fish is that by default it can tab-complete program options and also shows a one-line description of what each of them does. (It grabs that info from the man page).

So much of computing is dedicated to solving problems that could be omitted.
I mean, that's precisely my thoughts on copyright and licensing in general but what can you realistically do?
Realistically, on an individual scale, you can pretend it doesn't exist and go on with living your life?
I very much would if only that pesky State didn't persecute me for that. Apparently, when I refuse to acknowledge the copyright and software license terms, other people get upset to the point of bringing the wrath of that Leviathan of oppression upon me! The nerve of some people!
Seriously. Just get up from the computer and go do something else. /s

We computer people are truly an odd bunch.

> and shell completion rarely works well if at all
I just tried fish. xinput --set-[TAB] and nothing. Apparently it doesn't understand the standard long-option format that is supported by xinput and documented in the man page. You have to know to omit the dashes and then it'll complete. And it's downhill from there.

Yeah I used to have all kinds of simple as well as supposedly sophisticated completion setups with zsh years ago but I've given up on it since then. It's always half-assed and half the time causes more problems than it solves. Same with bash. There are some places where I must resist the urge to try complete a filename because the shell starts trying to figure out which target it can complete from a Makefile in a large build system and just freezes. The only practical way out is to interrupt and type the command again or wait a stupidly long time. There are other issues like completion trying to be smart and filtering out things it thinks you don't want to complete. Nothing is more frustrating than a shell refusing to complete a filename that you know is there.

I run fish. I was able to get long-option completion for gcc, polybar, firefox, man, emacs, xrandr, and fish itself. The only command I was not able to get long-option completion for was xinput. You just picked a bad program to try.
I'm with you. Terseness is paramount.

I could never overcome my repulsion for Java and ObjC because of that. On the other hand, I fell at home with crazy RegEx that look like line noise to most people.

I think shells could use something like a built-in eldoc[1], in addition to tab completion. It would make terse command line interfaces much more usable if you could see what the positional arguments were for.

[1]: https://docs.cider.mx/cider/config/eldoc.html

I hate .methodNameAsLongAsMyArm as well, but there's the opposite extreme:

As a beginner, I liked short variable names. When I came back a few months later, I learned my lesson. Years later? easier to just start over.

I like long form version. It helps me remembering what it does and why. Eg: `iptables --insert INPUT --protocol tcp --jump ACCEPT` was more helpful to me than `iptables -i INPUT -p tcp -j ACCEPT` when told how to allow TCP traffic.

For everyday command like `ls -l` I don't mind but anything more serious I take a more cautious approach.

The few scripts that I've written for personal use generally lack documentation or help commands of any sort; instead, they take all possible straightforward variants I can think of for each command (`--config`, `--config-file`, `--cfg`, `--conf`, etc). They usually convert everything to lowercase before processing, too. It's easier to fail safely on too much/too little input than it is to provide actual help.
Spaces don't make anything more descriptive, they just cause completely unnecessary quoting and escaping hassle.

The amount of time that has been wasted by Windows using "C:\Program Files" instead of "C:\Program_Files" far outweighs any highly questionable aesthetic benefit IMO.

On the other hand, how much broken code has been fixed to properly deal with paths just because of that? I'd argue that to be a major benefit. Same with Windows Vista forcing developers to write applications that work properly as a non-admin user.
Short option for interactive terminal. Long option in automation.

I’ll be damned if I have to remember or lookup what -n means to some obscure program, when reading someone else’s script. Exception given for super common tools where everybody knows like ls -la.

With the disclaimer that shell scripts, especially ls, aren’t exactly suitable for reliable automation in the first place.

What's wrong with camelCase? It's easier to type than snake
There's a tendency away from snake_case and towards kebab-case in things you interact with via CLI. Even moreso towards nocase.

Programs like Powershell eschew ease of use in CLI for readability in scripts.

Snake_case is problematic for including filenames in TeX also. This is a big no for me, even if I find it more readable than the other.
> Even moreso towards nocase.

Nocase (did I break a rule by writing it that way?) seems great when you're enmeshed in the domain and you can see the implicit separators, but then someone looks at your naming from the outside and you're guaranteed to have an 'expertsexchange' in there somewhere.

Powershell is case-insensitive, so camelCase is only a writing preference
camelCase is objectively harder to read than snake_case or kebab-case, though familiarity can mitigate that.
I'd argue it's at most a tiny bit harder to read, and a lot easier to type. On balance I'd rather avoid making a pinky key one of the keys I have to use the most.
"On balance I'd rather avoid making a pinky key one of the keys I have to use the most."

And you use something else than your pinky finger for the shift key specifically when typing capitalized letters for camelCase?

At least it's where they sit naturally on the keyboard. And the shift key is wider specifically so you don't have to be accurate with your pinky when you're pressing it. The underscore is one of the least ergonomic keys there is. And you need both pinkies to do it
I might be misunderstanding. On all layouts I'm familiar with the underscore key is directly next to one of the shift keys, or left of backspace. Neither layout requires the Vulcan death grip. Shift should always be under your pinky fingers to avoid contortions.
On the US layout it is next to the zero key on the top row.
Having used a lot of all the formats, it's argue it's a lot easier to read an a tiny bit harder to type. For typing it's basically just an extra `-` because unless your alternative is nocase.

For reading, CamelCase has 2 significant ambiguity issues: similarity between I and l, and what do you do with acronyms. Acronyms wouldn't actually be a problem if everybody just wrote them would in snake_case (i.e. only capitalize the first letter), but they don't and so it's anyone's guess whether you're going to get "Id" or "ID".

There's also a minor issue where if you're on a case-insensitive file system it can be a little difficult to change casing, but adding/removing underscores is easy.

(comment deleted)
Adding an underscore everywhere is horrible! The spacebar is huge, and gets your thumbs basically to itself because space will be one of, if not the most commonly typed key. To replace that with one of the least ergonomic keys makes no sense.

And if CamelCase is so hard to read, why is it the norm for "high level languages"? Shouldn't those be optimized for ease of use?

> And if CamelCase is so hard to read, why is it the norm for "high level languages"

That's over-selling it a bit. It's more common, but not dramatically so. Outside of class names, CamelCase isn't the norm for Python, PHP, CSS, HTML. It's also not the norm for shell scripting, but shell scripting has horrible readability for other reasons.

I believe CamelCase is more common for languages like Go, C#, and Java because they grew up in large organizations where having god objects/classes with 400 methods is kinda normal and having aMethodWithAReallyLongName is pretty common. One of the advantages of CamelCase is that it does shorten really long names.

I could infer a lot about the second and what those params mean and what they do.

The first one is some magical incantation.

Sure. One could also make "move-down-one-line" be the incantation to move the cursor down a line in vi, but I prefer j.

Ergonomics isn't all about making everything self-descriptive for someone seeing the thing for the first time. It's about making things comfortable to actually use. If it's so long and complicated that you can't even remember how to do it, it's not very comfortable to use. Even if I could remember, xset m 0 0 is still far more comfortable.

And fwiw you still don't know what 0, 1 in accel profile do; you need to look that up or take a wild guess, and if you want to use that command, you'll also have to know how to look up the device because chances are yours is not the same as mine. So it's not any less magical in the end, just more verbose.

The "cool" thing about the xinput command is that you don't even find accel profile in the man page. You gotta look elsewhere if you want to understand what it is and what it does and what the parameters are.

xset m? Yes, that is documented in the man page.

It should be based on frequency of usage. I can tell you that moving down a line in vim is a little more common than toggling the mouse acceleration.

I would never even type such a command. I would just copy paste it once.

Yeah well, given that mouse acceleration tends to be on by default, I need to turn it off every time I'm on a fresh install or computer I haven't used before. The last time I needed that was yesterday.

I don't want to waste time searching for a command to copy-paste when it could just be made short, simple, memorable and ergonomic. I could type xset m 0 0 faster than I could open a browser and ask google how to disable acceleration with libinput. And again: you can't just copy-paste the xinput command unless you're lucky enough that it matches your device. On my new computer, the device has a different name than on my old laptop even though it's the same damn mouse.

It should be, but how would you keep track of usage frequency?

At least it would push all the "This switch was added by someone playing with UNIX at a university in 1986 and hasn't been used since" options to the end of the list.

> Ergonomics isn't all about making everything self-descriptive for someone seeing the thing for the first time.

We're talking about `xset`. It doesn't make sense to optimize that for usage of more than once a year.

The less frequently I need something, the more frustrating it is if it's not short and memorable (or easy to look up in the synopsis or built-in help). Forgetting and googling a needlessly complicated command over and over again every year isn't fun.

xset achieves that perfectly. If I somehow didn't remember how to set mouse acceleration with it, a quick glance at the synopsis immediately tells me. Or I can just run the command and it'll tell me:

    To set mouse acceleration and threshold:
         m [acc_mult[/acc_div] [thr]]    m default
Zero frustration, and the command is so short and simple that I end up remembering it without trying.

This is something I've observed more than once: I easily memorize useful sets of one-letter flags even if I can't remember or know what they all stand for. This just doesn't happen nearly as much with long options. Commands like ls -ctrl or ss -nap quickly become part of my repertoire even if I don't use them very often, but I really couldn't remember ss --numeric --all --processes (if I had written that from memory, it could've ended up as --num --all --pid or --numeric --any --process), and I don't even know what the corresponding long options for ls are. In the rare case when I have to deal with an option that has no short equivalent, I feel like I have to look it up every time if it's been longer than a few weeks.

You talk of optimization but I think this is just a very basic (and reasonably successful) attempt at sane design. It's not like someone had to go far out of their way to make this in a manner that isn't batshit insane.

But which case should software interfaces optimize for? Ergonomics of someone who uses a tool frequently, or interpretability for casual by-standers of some out-of-context shell command?
Another interpretation is:

On the first, you think you know what it does, but you're not sure. So maybe it gets looked up.

On the second, you know you don't know what it does. You so know to look it up.

Personally, I'll take the second. Assumptions during debugging are dangerous things.

I've a feeling you will hate powershell
Needlessly long parameter/command names and the bizarre insistence on capital letters are the #1 and #2 reasons I detest PowerShell. Like GP, I resent that Linux tools are moving in that direction.
Long option names are more descriptive, more easily distinguished, and easier to remember. Your shell should be intelligent enough to provide tab completion for option names, assuming it is configured to.
> Long option names are ... easier to remember ... Your shell should be intelligent enough to provide tab completion

They are so easy to remember that you need to configure your shell to remember them for you?

(comment deleted)
Long option names are more difficult to remember because a long option name can be spelled multiple ways and it is difficult to remember which spelling is correct.
>Your shell should be intelligent enough to provide tab completion for option names, assuming it is configured to.

Wait, are you saying that I need to change my shell or config to make up for another tool's poor design?

No, thanks.

IMO, powershell got it right. Yeah, it’s syntax is strange, but it has standard flag usage with proper autocomplete, and you can shorten any flag the way you want (eg. fuzzy match) if it is unambiguous.
Cue nmcli (CLI for Gnome's NetworkManager) which uses UUIDs for everything and (at least a while ago) did not accept partial-but-unique UUIDs. Basically goes "nmcli connection up 5095665a-d82c-4ae6-8964-283623387941".
By this point, I'm pretty sure there are people at gnome who compete to see who will make the stupidest suggestion that gets put in production.
It's a Gnomespiracy to determine whether worse is actually better.
Fits right in with COP26. (Could Of Punted?)
Weird, I haven't had to do this. Most(/all?) connections have nice names you can see with `nmcli c`... and so I can do `nmcli c up id DroidNet` and that's pretty dang nice. Pretty sure this worked with Ubuntu 14.04 (though, nmcli has gotten much more featureful since then)

(The ability to shorthand connection->c and similar is great, too; obviously not unique to nmcli)

The problem is we're optimizing for "easy to learn" rather than "easy to use".
In a world of broken promises and tool churn, minimizing tooling investment isn't laziness, it's a defense mechanism.

This is a lesson I had to learn the hard way, multiple times.

I've learned this lesson too, and I now avoid using any tools that have broken backwards compatibility in the past 20 years.
That may be a part of the problem but honestly I don't feel like all these new crazy interfaces are easy to learn either. I mean how do you come up with the lithany xinput calls for? You need to understand the syntax for specifying a device. You need to know that you're to set a libinput property, and you need to know the name of that property, and it's not documented in xinput man page, and of course you need to know the values to pass which again are not documented in xinput man page. You can play with --list-props and then take your search elsewhere because it is completely opaque and doesn't explain what the properties actually do.

I suspect the number of people who figured all that out without having to find it by googling / arch wiki / whatever is very very low.

Now I'm not gonna say xset is the easiest interface to figure out, but the syntax for setting mouse acceleration is right there in the synopsis, and if you search down the man page, you'll learn a little more (and also if you just run xset without arguments, it'll tell you how to set mouse acceleration). It might not be the best designed tool but it's something I learned back in the day as a teenager just by looking at the man page.

I think the real issue is that people nowadays are designing these interfaces to be consumed by interactive configuration tools, GUI apps, and desktop environments; they're more dynamic, more complex, more flexible, but not easier to figure out, not for you on the command line. The command line is just a last resort. Second class citizen if you will.

    alias mouseoff='xinput set-prop 11 "Device Enabled" 0'

    alias mouseon='xinput set-prop 11 "Device Enabled" 1'
Kind of ridiculous if you ask me.
It is, but they actually have a shortcut for that (--disable, --enable).
Direct quote from my console:

    $ xinput --disable
    Segmentation fault (core dumped)
On some level it makes sense. The problem with the command line is familiarity.

How often do you reach for iptables? If you're like myself, and most home/desktop users, then probably once in a blue moon to set it up and then you leave it alone. But a system admin? Maybe they touch it a few times a week or month. Every time I use iptables I have to relearn how Linux networking works.

Similarly, the xset/xinput thing. When I need those tools I just create a script or throw it in .bashrc. I adjust the settings once and will not touch them again for a couple years. It makes sense to have long parameters that are readable. I can look at my .bashrc and see exactly what device is getting adjusted.

imho, the fundamental problem is using space as a delimiter. Also, case-sensitivity is a disaster for ergonomics.

If you had comma-delimiting like in an algol-derived language, you wouldn't need to quote things with spaces.

edit: also, code is read more times than it is written, so optimizing for readability over brevity is generally a good move.

Well, if you think that's bad, behold the recent trend in network interface names on Linux.

We started out with 'eth0', 'eth1', etc. Which adapter was which could change when adding and removing a network card. That was bad, so that prompted the evolution.

Now we have 'enp1s0', 'enp0s31f6', 'enp13s0' and many similar variations. These are supposedly more stable across device changes. As it turns out, it wasn't.

But wait, there is more! Now we have the "predictable names" scheme that produces interface names that are even longer, and not even slightly easier to remember.

Read about the whole sorry saga here:

https://wiki.debian.org/NetworkInterfaceName

I do get that it is not an easy problem to solve, especially in the face of removable network interfaces (like USB Ethernet / WLAN). But surely this is not the best we can do.

I was actually ranting about this on IRC last night (yeah now my laptop has two enp* interfaces and enx[MAC])..

One thing I like about OpenBSD is that buses are scanned and drivers probe in order and there's no race between drivers coming up. Unless your hardware is physically tampered with or broken, all interfaces come up with the same name across reboots. Linux isn't like that (even if you don't touch your hardware, interfaces could swap across reboots), so you need to do something about it.

As is typical on Linux, the default is unergonomic and if you want something nice, you're on your own to make it so.

If you already have userspace daemons responsible for device insertion and naming, it really wouldn't have been so hard for it to e.g. automatically add a config file / database entry for each interface the first time is seen. So the devices that came up as eth0 and eth1 are still eth0 and eth1 on the next boot; if I unplug eth0 and add a new card, the new one would be eth2 because eth0 is still reserved for the first card I had.

> add a config file / database entry for each interface the first time is seen.

Ubuntu did that with their persistent-net.rules udev rule. That was a part of the PITA of the old naming.

> These are supposedly more stable across device changes.

No. These are stable across reboots. The old eth? weren't. And yes, that had been a PITA.

If netwok interfaces were files we could just have both short names and stable names, like what we have for block devices.
These changes are meant to make it easier to read and understand command-line incantations (and to make them more explicit, which is always good), because the command-line paradigm, being text-based, imposes an unavoidable trade-off between ergonomics and understandability/ease-of-use. It sounds like you prefer ergonomics - although I wouldn't be surprised if most users would prefer ease-of-use.

Of course, if one doesn't write a CLI to begin with, this trade-off doesn't exist - you can have your cake and eat it too.

I don't use spaces because it's so much faster to type filenames out (including with TAB-completion) in the terminal.

I do, however, use Cyrillic (UTF-8) in filenames, and I regularly try out if moving a file into ASCII-path will let some programs open it (half the time it's that when I am having trouble).

Spaces in file names are a bad idea because spaces delimit the name of separate distinct files,

At least in my crazy old illogical head anyway.

File names should be long enough to clearly communicate meaning/purpose/context, no more no less.
This is a UI/UX problem that I only face when dealing with shells and shell scripts. Never had any issues when spawning processes from within languages/runtimes that support sane argument arrays.

sh, bash and cmd.exe are shit. The shell needs serious rethinking.

I see that there are lots of comments about problems of TAB-completions with filenames with spaces in this comment section and I am frankly puzzled: both Bash and cmd.exe actually TAB-complete those perfectly fine, inserting quoting where it's needed.
I seem to remember bash losing preferred escaping when TAB-completing, but can't reproduce it now with 5.0.17.

Eg. you'd type `ls -l "Spaced [TAB]` and it would turn it into `ls -l Spaced\ Name`. I remember similar annoyances with other special shell characters (eg. single quotes, dollars, slashes), but that all seems to behave sane now.

I didn't even know this was a thing, but can't say I've ever preferred an escape style. I actually use backslashes a fair bit, usually just with spaces. I tend to reserve double quotes for variable or shell expansion, explicitly.
It's not so much about a preference, but your cursor would jump about and you'd need to be on the lookout if you wanted to edit the completion (eg. to change the extension).
> inserting quoting where it's needed

You have to remind yourself to do this manually in scripts if you don't want to see lines full of "No such file or directory."

One of the reasons the shell is broken is because the character they use as an argument array member separator is something that regular people use to distinguish between two words, such as in a file name.

Well, writing scripts would be much less painful if $VARNAME did not explode into pieces by default. Alas, this ship has sailed long ago.
IMHO, it's possible to add a flag to bash, which will turn on this behavior, so problem can be fixed, but it will diverge bash from POSIX sh a lot.
And where it isn't needed. If you have a path that contains a variable and a space, bash will happily escape the $, making the path invalid. See the following:

  $ cd $HOME
  $ mkdir my\ dir
  $ ls my[tab]
  $ cd /
  $ ls $HOME/my[tab]
  ls: cannot access '$HOME/my dir/': No such file or directory
That error is because when you press [tab], bash changed the path to \$HOME/my\ dir/ but that isn't obvious from the output and I couldn't find a proper way to include the tab-expanded result in the transcript.

(edit: this is on GNU bash, version 4.3.48(1)-release but I've seen this behaviour for years)

Depends on the Bash version, I guess? Mine is 4.4.20(1) and when I do "cd $HOME/my[TAB]", it replaces the input line with "cd /home/joker/my\ dir/", and pressing [ENTER] changes the directory to '/home/joker/my dir', as can be seen from the prompt.
This is a difference between $@ and "$@" (note the quotes):

  $ cat proba.sh 
  #!/bin/sh
  echo "Using quotes:"
  for i in "$@"; do echo "$i"; done
  echo "No quotes:"
  for i in $@; do echo "$i"; done
  $ ./proba.sh "ho ho ho"
  Using quotes:
  ho ho ho
  No quotes:
  ho
  ho
  ho
Damn I didn’t know that. Thanks
Looks like I'm in the minority. I always use spaces and non-ASCII characters in filenames.

In many languages it's a requirement. For example, in Romanian, there are 8 words that collide with „fata“ if you remove the diacritics (fata, fată, fața, față, făta, făță, fâța, fâță).

Given that we have to use diacritics, spaces don't seem like a big deal.

Hmmm, I thought I was fluent in Romanian (born there and lived there for 26 years), but I only know 5 of those 8 words...
That doesn't seem unusual. Only the first 5 are very common.
According to Google Translate the first two are "girl" and the rest are "face". =)
* fata - the girl

* fată - girl

* fața - the face

* față - face

* făta - was giving birth

* făță - a small fish, or a child who won't sit still

* fâța - was fussing

* fâță - variant of făță

As you might infer from the first 4, Romanian uses postfix "the" and for singular feminine words you can't tell the difference if you use only ASCII.

Google Translate is a horrible tool for "translating" single words or lists of unrelated words.

Use a proper dictionary for that. The very nature of statistical models makes proper translation without context impossible for these systems, especially when uncommon words and diacritics are involved.

So how did you deal with it in the 80s/90s?
As you would assume: use ASCII and deduce from context. Many people still do that.

That has lead to phantom diacritics: reading letters in unfamiliar words/names based on what you assume they are. For example some pronounce Chirica as Chirică because they assume someone forgot to type the breve in ă.

I call it the habanero trap. There is no ñ in "habanero", yet a lot of people say "habanyero", probably by analogy with "jalapeño".
Not sure about Romanian, but for many other languages people essentially came up with transliteration schemes (multiple, incompatible, ambiguous) to squeeze your language into ascii.

The resulting text was understandable by the "computer people" but not the general population who did not use the networks back then, perhaps somewhat comparable to when some time ago USA parents encountered the "SMS slang" used by their teenagers.

Back in the day there were dozens of character sets that were alternatives to US-ASCII. Having once worked on an Email client, I needed to bake in a bunch of translation tables to convert stuff sent that way into UTF-8.
> Given that we have to use diacritics, spaces don't seem like a big deal.

There is one big difference: CLI utilities don't usually care about diacritics (though encoding issues can throw a wrench in that), but they care a lot about spaces. So putting spaces in filenames requires properly quoting or escaping parameters, whereas diacritics does not. That makes one-off shell snippets and scripts a lot more annoying (though TBH I tend to shy away from those anyway, these days).

We have a few words that depend on diacritics to be unique in Czech as well - though not as bad as this example - but people just manage without. Hell, I don't even bother installing the Czech keyboard, if I REALLY need it (like in names), I just google for words that have the character and copy it
>In many languages it's a requirement. For example, in Romanian, there are 8 words that collide with „fata“ if you remove the diacritics

That is what context is for.

So do I. I have a language, and I'm not afraid to use it. My computer should speak it just as well as I do.
There's a server at work that name with a non-ascii character. I've run into compatibility issues lots of times where I can't connect. I prefer to just use English with ASCII and be happy
Server names are different. They are by and large machine-facing identifiers, whereas filenames have a 50-50 split of whether they are machine-facing, human-facing, or both. They makes their support of Unicode a much more critical (and appealing) proposition.
everything is a file
One of the main reasons why Windows used "Program Files" and "Documents and Settings" was to force the programs (and programmers) to deal with paths with spaces. And you know, for the most part it kinda, more or less worked out although of course even today you will find programs that ask you to install them in a folder without spaces in the path.
VFAT and stuff like that actually provided alternate names like PROGRA~1
Yes, I was doing code to quickly read FAT folders (on a micro controller) and got to the bit about filenames more than 8.3. I decided my life was too short (and processing time) to go and sort out what the "real" file name is. Enforced 8.3 as a requirement!
The main culprit for space issues is stuff relying on BAT or CMD files, where escaping variables seems to be a black art.

Sadly such set includes loads of Java programs. If only SUN had shipped a standard way to generate isolated exe files in 1998... but they worked under the presumption that you'd have a JVM already there, because distributing that monster was difficult in dialup times, so you could just hand people a jar; and the enterprise market did not care, since they had webapp servers. Sadly it's an "optimization" that became obsolete very quickly but wasn't rectified until it was too late (java 9+).

> The main culprit for space issues is stuff relying on BAT or CMD files, where escaping variables seems to be a black art.

Actually it isn't, just use double quotes and add a '~'. It's just about the only thing batch files handle better than shell scripts. set "VARIABLE=%~PATH"

And that was a good idea, if only Microsoft also fixed the CreateProcess function, Windows would be somewhat sane in this regard. But somehow nobody seemed to think of it. Seriously, look at it:

https://docs.microsoft.com/en-us/windows/win32/api/processth...

The arguments are a single string. So you want to pass parameters with spaces in them? You've got to add quotes and stuff all of that into a single string. Instead of doing it in a more sane manner, like oh, the arguments to main().

The root cause is that argv isn't a first-class citizen like on linux, but an abstraction. The kernel only cares about a single string argument. If you use main instead of WinMain, the CRT will transform the single string into an argv for you.

Oh and cmd.exe uses a different escaping scheme than the CRT.

Microsoft is in full control of the Windows kernel, so they can make it care about whatever they want to, and one would think better argument passing would be a nice quality of life improvement. Less nonsense for developers to deal with, and less weird bugs on the platform.
Sure, but MS values backwards compatibility a lot.

They aren't going to break existing API or bloat the kernel with a bunch of functions that do the same thing.

They can either add a new API which almost nobody would use ― because everyone already learned to use the existing one and either reused or reimplemented the MSVCRT's logic so that most of the software parse the command lines the same way; or they can literally break every single program in existence by breaking the interface of CreateProcess ― which is just as likely as Linux breaking the interface of execve(2).

Giving CreateProcess a new flag so it would to correctly accept "path\\to\\my\\program.exe\0arg_1\0second argument\0argument with literal \" symbol" (with an implicit \0 terminating it) as lpszCmdLine is an easy part; the hard part would be forcing everyone to switch to using it.

Also, I'm pretty certain this processing happens in the user space, and Win32 API is already bloated beyond any belief.

maintaining backwards compatibility means maintaining silly decisions, and Microsoft does both.
They may have thought that would happen but I saw just as much stuff end up in C:\Windows or \Users or (always my favorite) those “Documents” that are really just “whatever random crap every app wants to put there”.
Yet in Microsofts own cmd tool I need to put quotes around my path if I want to refer to any files/folders below those folders.
That annoys me every time I use a Windows system. It was a terrible decision, especially since both the command prompt and the new powershell doesn't accept like bash a backspace before a space, you have to quote the whole path! I get that most users on Windows don't use the shell, but as a developer I do a lot, and every time it's a pain (no wonder they added the WSL in Windows after the failure of Powershell...)
Why would they accept a backslash? Backslash is a path separator on Windows. In most Windows programs, you don't even need to escape the space - arguments can contain spaces and it will understand it, like `notepad My file.txt`

The escape character on PowerShell is backtick, and on cmd it is caret. You don't need to quote everything.

Well, you should still be afraid! Be very afraid! Seriously: only a few months ago I was confronted with a video encoding tool that didn't work properly when the file names contained spaces - so yes, even in 2021 it's still safer not to use spaces in file names...
Not to mention most naively written bash scripts!
Shells are indeed the main culprits for the continued fear of spaces, but not the only ones. A lot of programs that deal with "metadata" which will then generate database tables and stuff like that, still struggle when working with any sort of special character. And the same for anything that, behind the scenes, just feeds text into regexes.
Just this weekend I learned that the Espressif Framework doesn't like it aswell.
So, born today, eh?—says the guy who still regularly runs into build scripts that cheerily command that they be run from directories without spaces, since that's easier than proper quoting in the script.
Well, I'm using makefiles old
Remember when we put + instead of %20? Spaces in URL's are still a nightmare IMO. I still get strange access log entries where some encoding went lose, especially in heavy Javascript enviroments.

Same goes for capitalisation. All filenames should be lowercase.

Maybe it's not strictly necessary, it can avoid headaches.

If I'm going to use the file in the command line, I won't use spaces, since I don't know what sick bug I might encounter.
(comment deleted)
I avoid spaces because they make tab completion more cumbersome in bash.
Same. For documents and stuff that I use in normiespace I give them friendly names with capitalization and spaces and such, but for anything I'm going to be working on via CLI I try to use filenames that will be easily chunked as "words" when doing things like double clicking it in terminal to select, ^w to erase it, tab completion etc.