> Microsoft intentionally made programs install to C:\Program Files on Windows 95+ to force programmers to deal with spaces in filenames.
Not least, it makes writing scripts for various shells and getting the quoting rules right an absolute pain as well...
/Users/{root, user0, user1, ... }...
/System/{Logs, Apps/{opt, container, ...}, Temp, Conf ...}...
/Devices/{Mount, sda, sdb, null ...}...
/Boot/...
> the system kept trying to replace folders in their original places.
This is the file that you want: $ cat ~/.config/user-dirs.dirs
XDG_DESKTOP_DIR="$HOME/"
XDG_DOWNLOAD_DIR="$HOME/Downloads"
XDG_TEMPLATES_DIR="$HOME/"
XDG_PUBLICSHARE_DIR="$HOME/"
XDG_DOCUMENTS_DIR="$HOME/"
XDG_MUSIC_DIR="$HOME/"
XDG_PICTURES_DIR="$HOME/"
XDG_VIDEOS_DIR="$HOME/"(Anyone who tried to package a program that hardcodes the “usual” binary paths know the pain)
Probably the easiest way to experiment these days is to create a VM and make snapshot, then start knocking down walls, just to see when and where the house collapses. Then revert and try something new.
There could be a competition!
So I ran two simple commands:
cd /tmp
rm -fr .*
and wondered why it was taking so long. <grin>> When a pattern is used for pathname expansion, the character ``.'' at the start of a name or immediately following a slash must be matched explicitly, unless the shell option dotglob is set. The filenames ``.'' and ``..'' must always be matched explicitly, even if dotglob is set.
This is definitely interesting though, and an improvement I would say
So either those low hanging fruits are higher than they seem, or we're all just a bunch of dwarves.
My bet is on the second option.
Will upstream accept such patches though? Sounds unlikely to me.
It's frustrating having to spend time to decide whether I should install a program in /var or /opt or /usr. What do they even mean!
So, I disagree with this convention altogether and use /apps or ~/apps now.
"While no one sane would put newlines in directory names, such corruption of the results could lead to exploitable vulnerabilities in scripts."
Want to see true craziness? POSIX file names are just a bag of bytes. They don't even have to be text, they can be anything (almost), there's no standard text encoding:
https://lwn.net/Articles/325304/
And in typical Open Source fashion, someone actually claims it's a feature: https://lwn.net/Articles/325398/ because hey, you 99.999% percenters can suffer so that I, 0.001% percenter can implement my wacky system.
$ mkdir hold
$ cd hold
$ cat ../wildname.c
#include <stdio.h>
int main(int argc, char **argv)
{ char n[256]; int i,j=0; FILE *fp;
for(i=1; i<256; i++) if(i!=47) n[j++] = i; n[j] = 0;
if(fp = fopen(n, "w")) { fprintf(fp, "hello world!"); fclose(fp); }
}
$ cc ../wildname.c
$ ./a.out
$ ls -l
total 16
-rw-r--r--. 1 luser lgroup 12 Nov 11 16:32 ??????????????????????????????? !"#$%&'()*+,-.0123456789:;<=>?
@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~?????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????????
-rwxr-xr-x. 1 luser lgroup 8464 Nov 11 16:32 a.out
Just because you can do something does not mean that you should.So anything not directly blocked by the software is allowed.
Ergo, clear specifications, strict yet flexible types and APIs, etc.
Otherwise, it's just bad design.
Too much choice for things like this is harmful IMO. Deep down I truly couldn't care less where the files end up, as long as that place is the 'right' place. There are too many 'right' places which makes it hard to find random things at a later date or when on a box you're not super familiar with. It's also a complete waste of time to think about it at all.
The “standard” doesn’t tell you what directory structure to use inside /etc to group related config files. The “standard” doesn’t tell you where an HTTP server should serve its files. Everyone just does their own thing which makes upstream docs incorrect and useless for newcomers.
The FHS, does actually answer both of of those questions. Files inside /etc/ should be grouped in subdirectories[0] andd the HTTP server should serve user-specified website files from /srv[1] and normal distro-provided files (such as the apache test page) from /var[2].
[0]: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s07.htm...
[1]: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch03s17.htm...
[2]: https://refspecs.linuxfoundation.org/FHS_3.0/fhs/ch05.html#p...
I’ve never seen that in my life, but I’m sure someone does that. This is one of those cases where the people who follow the standard are increasing fragmentation
So, given some data, say a file and/or directory, maybe from saving a Web page, that is relevant to subjects A, K, T, and Z, where in the file system directory trees to put that data?
My solution: Put the data in a directory for one of the subjects A, K, T, or Z without thinking very hard about which of these. Then go to a file I call FACTS.DAT (right, an old idea with an old 8.3 file name!). I maintain that file with a few, simple editor macros. So, sure, the file is a catch-all for entries of random short facts. And each entry starts with a time-date stamp and a list of key words. So, in the case of subjects A, K, T, or Z, include the key words appropriate for each of those. Then in the body of the entry, put the tree name of the file/directory where did store the data.
In a few seconds with my favorite text editor I can append an entry or search for an entry.
So far this year I have put 686 entries in the file FACTS.DAT for about 2.1 entries per day. For anything like current personal computers, handling such a file is trivial.
The idea works great!
/opt is for standalone packages, so if it’s a single file, no.
/bin is only for stuff needed on single user mode, so probably not (unless that’s what the binary is for.
/usr/bin is going to typically contain files installed by your package manager and should probably be left unaltered by human hands.
The deps I would assume /usr/local/lib but it hasn’t ever come up for me.
This is one of the big advantages of using a pre-made advantages of using a ready-made Linux distribution: beyond the convenience of having an installer or easy to install packages, you get some assurance that the system as a whole has been thoughtfully put together.
Arch Linux for example symlinks /bin and /sbin to /usr/bin and /lib to /usr/lib among other things.
If you expect other users to be able to execute the program, then you should put it in either `/usr/bin` or `/usr/local/bin`, depending on whether the former is already being used by a package manager. `/opt` is generally for self-contained software that doesn't play nicely with the rest of the system, but might still be installable through the default package manager.
Can't remember the last time I had a problem arranging this. If using autotools, which covers 95+% of stuff, it's usually a question of something like "./configure --prefix=$HOME/usr".
(If I want to share stuff between users, /usr/local/ is of course a better place. macOS is a bit more restrictive, so I have a separate user for this, whose /usr folder is readable by everybody.)
On freedesktop systems there's the ~/.local directory which is supposed to be a mirror of the file system hierarchy. Seems like a good place for bin, lib, include directories.
And conditions that formed separation are long gone, Arch Linux symlinks most of it:
/bin -> /usr/bin
/sbin -> /usr/bin
/usr/sbin -> /usr/bin
/lib -> /usr/lib
/lib64 -> /usr/lib
/usr/lib64 -> /usr/lib- Things installed in /, if it’s different from /usr, are generally not to be touched;
- Things installed in /usr are under the distro’s purview or otherwise under a package manager, any modifications are on pain of confusing it;
- Things installed in /usr/local are under the admin’s purview and unmanaged one-offs, there are always some but overuse will lead to anarchy;
- Things installed in /opt are for whatever is so foreign and hopeless in not conforming to the usual factoring that you just give up and put it in its own little padded cell (hello, Mathematica);
- Everything is generally configured using files in /etc, possibly with the exception of some of the special snowflakes in /opt; the package manager will put config files meant to be edited there and expect the admin to merge any changes in manually, and sometimes put default settings meant to be overridden by them in /usr/share (see below)—both approaches can be problematic, but the difficulty is with migrating configuration in general, not the FHS as such.
There used to be additional hierarchies like /usr/X11R6, and even a /usr/etc on some (non-Linux?) systems, but AFAIU everyone agrees their existence makes no sense (anymore?), so much that even FHS doesn’t lower itself to permitting them.
The distinction between / and /usr might appear to be pointless as well, and nowadays it might be (some distros symlink them together), but previously (especially before initial ramdisks were widespread) stuff in / was whatever was needed to bring up the system enough that it could netmount a shared /usr.
Inside each of /, /usr and /usr/local there is bin for things that are supposed to be directly executable, whether binary or a script and all in a single place; share and lib for other portable and non-portable (usually but not necessarily text and binary) shared files, respectively, segregated by application or purpose; finally, due to the dominance of C ABIs and APIs on Unices, the top level of lib also hosts C and C++ library files and there’s an additional directory called include for the headers required to use them. Some people also felt that putting auxiliary executables (things like cc1, the first pass of the C compiler) inside lib was awkward so they created libexec for that purpose, but I don’t think the distinction turned out to be particularly useful so not all distros maintain it.
That’s it, basically. There are subtler but logical points (files vs subdiretories in /etc) and things people haven’t found an obviously superior solution for (multilib and cross environments), and I made no attempt to be historically accurate (the original separation of / and /usr happened for intensely silly reasons), but those are the fundamental principles of the system, and I feel it does make sense as a coherent implementation of a particular design. Other designs are possible (separation by application or package not purpose, Plan 9-ish overlays, NixOS’s isolated environments), but that’s a discussion on a different level; the point is that this one is at the very least internally consistent.
Re the unfriendly names ... I honestly don’t know. Newbie-friendliness matters, but it’s not the only thing that does; particularly in a system intended for interactive text-mode use, concise names have a quality of their own. There’s a reason I’m more willing to reach for curl and jq rather than for httpx and lxml, for regular expressions rather than for Parsec, and even for cmd.exe, as miserable as it is, rather than for PowerShell.
I feel weird that no HCI people seem to have seriously considered the tension between interactive and programmatic environments and what the text-mode user’s experience in Unix says about it, but even Tcl, which is in many ways a Bourne shell done right, loses something in casual REPL use when it eliminates (as far as idiomatic libraries are concerned) short switches. Coming up with things like rsync -avz or objdump -Ctsr is not very pleasant initially, but I certainly wouldn’t want to type out the longhand form that would be the only possible one in most programming languages (even if I find their syntax beautiful, e.g. Smalltalk/Self).
As I recall, there were very good reasons for separating / and /usr (as well as /home and /var). The biggest one was that various Unix kernels would panic[0] if / was full. But that issue was almost universally fixed by 1990 or so.
And netmounts of pretty much everything other than / were pretty common for many years, due to the high cost of storage.
So no, the reasons weren't silly, they just don't apply to more modern systems.
(I have an old Unix intro book that describes /usr as user home directories, the rest is a second-hand retelling[1].)
[1] http://lists.busybox.net/pipermail/busybox/2010-December/074...
See my post to this thread at
In your home directory.
Yes, the Linux/POSIX model is confusing, but the split is to segregate administrative domains:
- / and /usr are the domain of the distribution. As a user, you should never install there. The administrative group is root.
- /usr/local is the domain of the machine admin. If the machine is yours to manage, you can install software there. The administrative group is staff.
- /opt/$vendor is the domain of third-party vendors. Each vendor (like Steam, Eclipse, Arduino Studio) can get its own subdirectory and its own administrative user group.
How would you achieve the same on Windows? How do you make sure the Adobe updater can only install new versions of CS, but not surreptitiously install a new (free!) spyware package under C:\Windows? How would you allow certain power users to share one Google Chrome installation, allow each of them to update it, but not let them install additional software system-wide?
I think the best model I've seen for consistent binary locations is the 'Applications' folder in Mac OS X, but it fails as well by retaining the /usr/bin elsewhere.
Also, as mentioned by the siblings to thia comment, the 'mess' has a purpose, and is less messy than it appears.
Want to manually install something? Into /usr/local it goes. Done.
The only way to handle this that I've been really impressed with is Mac's "Applications" folder. Unfortunately, I dislike most other things about Mac.
You can do `configure --prefix=/Program\ Files/<app>` if you want.
Offering too many similar choices leads to mess. There's nothing fundamentally different between using one or more of these options and using the only option, except that in the second case there isn't any opportunity to make mess.
> You can do `configure --prefix=/Program\ Files/<app>` if you want.
Thanks for the tip! Can't do that with distro repo software though :-/
What does that even mean? When you install something, you put it where you want it.
If you don’t like where your distribution puts files, choose a different one. Not all of them use the same convention.
/var stands for variable data--like log files, cache directories, spool directories, etc. You shouldn't put executables there. Ideally you should be able to set the noexec flag on it.
`/usr` actually exists because the original UNIX developers ran out of disk space and had to attach another disk. The difference between /bin and /usr/bin is not worth it and even Debian symlinks /usr/bin to bin.
But your distribution's package manager should be putting stuff in /bin or /usr/bin, not you. Anything that follows the regex "{asterisk}/local{asterisk}" is something the system owner can do whatever with. So you should be using /usr/local/bin or $HOME/local/bin. I don't know why there's no /local off of the root. (One thing I do on my own systems is make and use an /etc/local although I think you're supposed to use something like /usr/local/etc).
/opt is for third party programs that aren't installed via your distro's package manager.
If you do this, any customizations you make to a system can be easily backed up by copying all dirs with local in the name.
There's multiple decades of tradition behind these names, but they do date back to the age where actual teletypes were used.
/Users -> /home
/System -> /usr
/Data -> /var
/Config -> /etc
/Boot -> /boot
/Ephemeral Temp -> /run
/Persistent Temp -> /tmp
The only real holdouts are proc/sys/dev which are the kernel and mnt/media/opt/srv which are really for the user/sysadmin and aren't really used by the OS anymore.It's not an oxymoron to have files which are temporary but not limited in scope to a single power cycle. For example, you could have a long-running process which you want to be able to resume if it's interrupted; /var/tmp would be an appropriate place for the state. The data is temporary because it will be deleted once the process is finished, but you wouldn't want it wiped out by a system reset. Generally /tmp is cleared at every reset, and is often a tmpfs mount, while files in /var/tmp are automatically cleaned up only when they reach a certain age.
Nothing will immediately break because you linked /var/tmp to /tmp. Whether it causes issues depends on the programs that you (or your users) run and how they make use of /var/tmp. However, if someone did have to restart a long-running process from the beginning because recent state information in /var/tmp was not preserved across a reset, I would say that is a problem with the administration of the system and not the program that stored its state there.
/tmp and friends are poorly named. They really should be /shared or /dmz or /freeforall or something.
* If you need service-specific tmp space use RuntimeDirectory or PrivateTmp if your app is hardcoded to /tmp.
* If you need service-specific persistent data that goes in /var/lib/your-app.
* If you need temp space for your user it's at /var/run/user/your-uid.
* If you need more than one user/service to share files but not everyone then god have mercy on your soul because all options are bad. There sure are a lot of them but none of them are at all satisfying.
Gentoo does, at least by default: https://wiki.gentoo.org/wiki//etc/portage/make.conf#PORTAGE_...
Caps are annoying to type, and difficult to remember (Do You Caps, or Do you caps, or DO YOU CAPS, etc).
Spaces are nuisances that bring no benefit. At best we should use non-breaking space for filenames, but that would be even more atrocious.
Of course, that's not perfect either, because a) decades of changes vs. compatibility have made it less clean in certain places, and b) pretty much all the POSIX paths still exist for unix-y compatibility, but overall it's like that.
Restructuring the directories is the easy part. You just delete the old tree and make a new one. You can also mount procfs and sysfs wherever you want.
The hard part is modifying existing software to work with the new tree. So many programs assume you have a "standard" file system tree. So many programs assume procfs is mounted at /proc. So many programs have hardcoded paths. Shared library locationd can become part of the binaries when they're compiled. It's insane and you'd essentially be creating a new Linux distribution.
Make the overlay of your dreams!
Works from File-Open dialogs and address bars and even in the command prompt you can even do "explorer documents".
The double grave I is used by some obscure orthodox religionious texts
Fortunately the future of the Windows API does look better since Microsoft has now added proper UTF-8 support since Win 10 1904. All you have to do is request it in the application manifest and the A functions will accept and return UTF-8.
Apple OSes use something they call "unichar" inside NSStrings. I'm not 100% sure what it is, but it feels like it's the same 16-bit wide character.
They really should have gone with WTF-8 [0] since the W functions generally accept WTF-16 and not just the valid UTF-16 subset.
for (int i = 1; i < INT_MAX; i++) {
if (dirExists("C:\\PROGRA~%d\\ProgramName", i)) {https://web.archive.org/web/20100107184218/http://blogs.msdn...
And so, yes, I’m certain someone must have done it, because it’s clearly bad idea jeans and so Murphy’s Law says it must exist.
one occurrence is enough to make devs care about it
https://docs.microsoft.com/en-us/dotnet/api/system.environme...
There are several other classes that take care of getting folders, least of which checking system variables.
Easier to add a flag to ignore case rather than fix bugs where files only differ by case and are therefore overwritten on a case-insensitive filesystem.
https://docs.microsoft.com/en-gb/archive/blogs/twistylittlep...
In nix at least you can call execve or other APIs that take a char argv[] and the whole problem is largely solved and you don't need to quote things.
So, some things were still being handled not quite right (whether that's because it shouldn't be allowed to be the username, or because programs should handle it being in the path, I'm not sure, but probably one of those.)
> C:\P̷̧̽r̸̬͘ŏ̵̮g̷̜͘r̸̦̋a̴͎̒m̶̲̈́ ̷̠̉F̵͇̈ĩ̴̫l̶̨͗ë̵̦s̸͚͆\
Easy fix!
A former co-worker changed his name in our auth system to include an apostrophe, so that whenever we handled names wrong he'd find it.
My best guess is "change the system time to be a timezone for which, during your work hours, the other-timezone is in a different day than UTC is" - but I'm still not sure what effect that would have on CI failures.
it keeps everybody on their toes lol.
If you consider spaces “unusual” I would say you haven’t encountered a single average user in your lifetime. Spaces in file-names is the single most common thing people have, outside programming environments.
As a x-plat developer, the only platform where I (still) regularly encounter these kind of bugs are platforms where solving problems through scripting is common, like Linux, where the primary means of operation is through stringly-typed statements getting parsed and processed in a untyped-fashion. It's not very reliable.
On Windows people more often use “real APIs” (because scripting doesn't really work as well), but then these problems just goes away.
Pros and cons, I guess.
thisismyconfig.txt vs this is my config.txt or this_is_my_config.txt
...i've forced myself to stop using spaces, character, and even cap. They are all constructs that provide minimal value for the extra complexity.
Just wondering, what is the readability of this for people who are dyslexic?
Switching to Chinese would also help eliminate the spaces issue.
Aside from parsing errors it just seems to lend itself to ambiguity.
Also programs automatically that turn paths into links don't work with spaces.
Saying, "who can't understand..." is arrogant, selfish, and an example of why normal people hate people in the SV echo chamber.
It's the same in any language.
Hugs who hurt you.
I'm also pretty sure most of us in any language use Slack, SMS or other forms of communication where text isn't necessarily presented in a grammatical correct manner and we all figure out what the person is saying.
Exactly how I feel every time Economics is brought up on HN.
If you wouldn't mind reviewing https://news.ycombinator.com/newsguidelines.html and taking the intended spirit of the site more to heart, we'd be grateful.
But Hacker News should do something about all of the anti-bitcoin and anti-anti-nuclear ideologies running around in here.
I don't really mind it that much but it'd be nice, it's really the only 2 extremisms I've experienced here, all other subjects are discussed in a fair manner.
There's no such thing as fair discussion about those topics here.
Otherwise what is your proposition, don't state any opinion unless you find a counter opinion commenter to match with?
Lots of folk here are pro-privacy and lots of folk are anti-bitcoin (and some of them will be the latter because they're the former) so I don't understand how you'd extended your position in a way that leaves HN with any value.
Your system is only intended for other programs to interact with? Go nuts, make hex UUIDs. Actual people are supposed to use it? You need separator characters.
I also don't see how those characters add "extra complexity" unless you're doing dumb things like text processing on paths and filenames (as opposed to using OS/library functions that handle paths correctly) - in which case, there's your problem.
A file system has a human interface and a computer interface. Don’t mix them. Let users give file names in whichever way they please.
could you please explain what you mean by that?
I changed my username to not contain a space because it was too annoying to deal with all the random dev tools breaking. The worst offender was probably npx on Windows [1] (resolved after four years by deprecating npx), but it was far from the only one (though the JS ecosystem was somehow the worst in this regard of all languages I worked with).
Saw a few hacks where malware authors used the RTL feature (which is baked into Windows) to obfuscate file extensions. It looked like .exe.innocuous-document.docx, but was actually .docx.innocuous-document.exe
League of legends doesn’t run until I sed files for instance.
Sure enough, they had SomeFile and were importing Somefile and it works fine on Mac but not on Linux (which, of course, is what our production servers use). It amazes me that "works fine on my machine" is still a thing when I definitely worked at companies that solved this back in the 2000s. It was solved. It was done. Then devs became enamored with running everything locally. Even dozens of microservices or databases. Even though JS is fairly isolated, you still have NPM packages that need built against the local OS and C/C++ library and compilers, etc. Which also has caused issues in the past.
Docker hasn't supported LXC since 2016, and stopped relying on it in 2014
https://www.docker.com/blog/docker-0-9-introducing-execution...
Actually no. At least on Windows Docker can do native Windows containers too
https://poweruser.blog/lightweight-windows-containers-using-...
When I got a new Mac, I just gave up and acquiesced to the case-retentive world :-(
I'm begging software developers to stop using subprocess APIs that take a string argument (system(), child_process.exec(), Process.Start(string)) and start using subprocess APIs that take an array of arguments (execvp(), child_process.execFile(), Process.Start(string, IEnumerable<string>).)
A small extra step but something you get used to if you spend a lot of time in the cli.
I set up symlinks which help navigating around but then the relative paths are wrong for git.
No thanks.
Friends don't let friends put spaces in paths
I never use / on Windows as a result.
These days using CMD instead of PowerShell should be rare enough and PowerShell certainly doesn't mind the slashes.
The problem with that is that YOUR code may handle it, but your tooling may not. If my code formatter break on spaces, I'm not going to change the formatter.
Last week I opened a ticket for a Firefox bug. Following up on the bug took me 2 hours in total.
FOSS is not free, you pay it with your time. And as with everything you pay for, we all have a budget.
Inject a Turkish 'I'. I don't know how to type or paste it here, but picture an English lower case 'i' that is upper case. It is a splendid way among many to shake out some loc bugs.
Mysterious character requirements that do not conform with Microsoft’s OS limits, limits on tbe fully qualified pathname length, etc.
Naming freedom needs a stdlib module
Enforce this in LDAP.
Strict convention is better than flexibility and predicting obscure edge cases that can fail.
Non-ASCII paths are extremely common (e.g. the user's home directory on Windows, for the large majority of users outside the English-speaking world) and spaces, punctuation and weirder characters will definitely happen when you least expect it.
Yes if you can avoid it then absolutely that's great, but I don't think most people can.
It's also not usually very difficult to deal with, as long as you actually spot the issue in the first place.
...and only hire people from the exact same background as you, who will never have unusual characters or accents in their name. And also make sure not to have any users who aren't exactly like you, and conform to this very narrow requirement. Surely, excluding 90% of the world won't hurt revenue in any way.
Use strict schema for the hardware interface, networking, physical stuff the user never sees. Microservice names don't need to be non-Latin. Database replicas, infrastructures, etc. And you're not going to piss off employees by giving them ASCII ldap/email addresses.
Use utf8mb4 or similar for storing names. Don't state "first" or "last". I've been through this rodeo too many times. You're not surprising anyone.
Anyway, all this was fine when we were on LDAP rather than Active Directory. So basically it's all Windows' fault.
But then your program will crash hard and unexpectedly when a user decides to save under "~/house plans" or ~/Téléchargements.
I think it's better to exercise this in CI, that's what CI is for.
Spaces are very useful for readability.
This will also break any code in external tools that are called during the builds of your application and do not handle spaces correctly for whatever reason, thus making it so that you won't be able to successfully finish the build.
Then again, you probably shouldn't be relying on technologies like that, but when you're struggling to keep an old enterprise system alive, causing yourself more problems is not necessarily what you should do.
Still a good idea in most cases, though.
Pro tip: rename your development directory (or even better: the workspace path in CI) to put a space and/or special characters in it.
Forces you to deal with this properly, and immediately ensures that every automated test checks this case without you having to remember every time. Hasn't been particularly inconvenient, since I'm autocompleting it 99% of the time anyway, and I haven't shipped a single path parsing bug since.