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 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
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.
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.
Yep, I recently got bit by this, someone checked in a branch named something like "x<-->y", Windows was unhappy. I think this is a git bug: git should escape these names for the native platform.
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).
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 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.
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.
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).
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!
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 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.
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.
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.
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.
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.
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.
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.
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.
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.
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?
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 more difficult to remember because a long option name can be spelled multiple ways and it is difficult to remember which spelling is correct.
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".
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)
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.
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.
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.
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.
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).
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).
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.
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
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.
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.
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 ă.
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
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.
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.
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:
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.
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.
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”.
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...
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.
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.
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.
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.
815 comments
[ 2.9 ms ] story [ 330 ms ] threadEdit: can't save, downloading works.
Apparently it's quite easy to reach the 260 chars limit
In the meantime:
https://serverfault.com/questions/9546/filename-length-limit... 255 bytes it is then.Firefox cut off at ~217, httpie at 255.
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.
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.
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.
https://stackoverflow.com/questions/1976007/what-characters-...
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.
It's cumbersome-ish, but can be made to work.
Then there's shell injection via files containing a newline character in their name...
Edit: replace $@ with quoted version which actually changes the behavior (I was wrong that the difference is between $* and $@).
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.
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.
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_
MISRA C:2004, 5.1 - Identifiers (internal and external) shall not rely on the significance of more than 31 character.
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.
If you are using cli tools of github written by a random person, then no wonder you will see non-standard approaches to UX.
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.
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).
We computer people are truly an odd bunch.
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 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.
[1]: https://docs.cider.mx/cider/config/eldoc.html
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.
For everyday command like `ls -l` I don't mind but anything more serious I take a more cautious approach.
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.
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.
Programs like Powershell eschew ease of use in CLI for readability in scripts.
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.
And you use something else than your pinky finger for the shift key specifically when typing capitalized letters for camelCase?
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.
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?
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.
The first one is some magical incantation.
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.
I would never even type such a command. I would just copy paste it once.
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.
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.
We're talking about `xset`. It doesn't make sense to optimize that for usage of more than once a year.
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:
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.
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.
They are so easy to remember that you need to configure your shell to remember them for you?
Wait, are you saying that I need to change my shell or config to make up for another tool's poor design?
No, thanks.
(The ability to shorthand connection->c and similar is great, too; obviously not unique to nmcli)
This is a lesson I had to learn the hard way, multiple times.
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.
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.
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.
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.
https://wiki.debian.org/NetworkInterfaceNames
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.
Ubuntu did that with their persistent-net.rules udev rule. That was a part of the PITA of the old naming.
No. These are stable across reboots. The old eth? weren't. And yes, that had been a PITA.
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 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).
At least in my crazy old illogical head anyway.
sh, bash and cmd.exe are shit. The shell needs serious rethinking.
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.
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.
(edit: this is on GNU bash, version 4.3.48(1)-release but I've seen this behaviour for years)
And I experience the problematic behavior on my Ubuntu VM. However, I can get the above describe expansion behavior if I run: shopt -s direxpand
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.
* 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.
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.
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 ă.
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.
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).
That is what context is for.
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+).
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"
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().
Oh and cmd.exe uses a different escaping scheme than the CRT.
They aren't going to break existing API or bloat the kernel with a bunch of functions that do the same thing.
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.
The escape character on PowerShell is backtick, and on cmd it is caret. You don't need to quote everything.
Ironically, even NASA doesn't like space.
https://www.nas.nasa.gov/hecc/support/kb/portable-file-names...
Same goes for capitalisation. All filenames should be lowercase.
Maybe it's not strictly necessary, it can avoid headaches.