> You will most likely want to create a default configuration file with sane and sensible default values the first time your program is executed.
Please don't. Include the example configuration in your docs (/usr/share/PROG..) and mention it in the manual. Statistically user will have hundreds of apps installed but will only ever customize a small fraction them. So creating config unconditionally on first run is one of the worst contributors to homedir pollution.
Another argument is version upgrades: if you create configur on first run, you forever bake in the set of options present in that version. If later a new option is added, user will have no idea about it.
Also, idempotency of a tool is a desired property that tool devs often invest a lot of effort in maintaining. Initializing default config on the first run is a trivial way to break it.
It's much better to just have a sane implicit default value for each setting when config is not present. Then you can list the default config in your docs or offer a CLI flag --print-default-config or --copy-default-config.
You upgrade the software and it no longer works right. No one else reports the same issue. Turns out the version you tun for the very first time wrote a config in a location you never looked, and that config is incompatible with latest version.
What I personally find more egregious are dotfiles and dot-dirs on Windows, created by half-baked ports of Unix-first software (such as `ssh`).
Windows has `%APPDATA%` and `%LOCALAPPDATA%` that are accessible with `ShGetKnownFolderPath`[0], using the appropriate `KNOWNFOLDERID`[1]; all programs should put their configuration and cache data in these paths.
Windows also doesn't know what the dot at the beginning of a file/folder means. Instead, it and NTFS have something that's arguably better: a hidden file attribute `FILE_ATTRIBUTE_HIDDEN`[2], that's again settable/gettable when a file/directory is created or polled, rather than regex-ing for a full-stop.
The worst irony is Microsoft software creating dot-files and dot-dirs on Windows[3][4][5].
I think "hidden" files are a bad idea. What's the point of hiding some of the files in a directory from user? It only makes things more confusing.
For example the folder might look empty but in fact it could contain thousands of hidden files. You want to delete it as it is empty but accidentally delete important system files.
Even worse, imagine if all files on an USB drive are marked as hidden. You see that the drive is empty but when you attempt to copy something to it see a message that there is no free space.
One more example. Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it. It turns out that Windows Explorer which doesn't hide dotfiles is much better for developing projects with Docker!
There should be no hidden files. We cannot do anything with Windows and their MS-DOS legacy but Linux could stop hiding dotfiles in GUI and CLI commands.
Hidden files on MacOS were used sparingly—the main instance of a hidden file is the file which stores an icon for a folder, if the folder has a custom icon. Hidden files are only hidden from the UI, they appear normally in the command line.
The standard Unix folders (usr, var, etc) are also hidden—to be honest, this is a compromise because the Unix filesystem hierarchy sucks, but we are saddled with it for backwards compatibility reasons.
I did appreciate the relative clarity of old macOS systems—everything in the OS was in “System Folder”, the rest of the filesystem was yours, and you could freely move applications without breaking anything, uninstall them by putting them in the trash, etc.
Personally, I think hidden files are OK, but we have lousy defaults, regardless of OS.
By default, Explorer hides hidden files (and goes one step further and doesn't display file extensions: why???), so do Finder, Dolphin, Nautilus, and even `ls` by default.
When I run ls I don't want to see all the configuration files. Just my files. I think that's the point of hidden files.
> One more example. Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it.
How likely is it that someone is going to want to edit a .env file and not know how to view hidden files?
>What's the point of hiding some of the files in a directory from user? It only makes things more confusing.
If a user doesn't know what .ssh/ or .bash_history are, and it can hurt them to accidentally delete or modify them, why show them by default? It's like training wheels on a bike.
>For example the folder might look empty but in fact it could contain thousands of hidden files. You want to delete it as it is empty but accidentally delete important system files.
If it is possible for a regular user to accidentally brick a system like this, it was doomed to begin with. If a user doesn't know what a dotfile is they shouldn't have administrative privileges, and if they do get them there is no safeguard to stop them destroying the system. It's not a dotfile issue.
>Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it. It turns out that Windows Explorer which doesn't hide dotfiles is much better for developing projects with Docker!
In what reality is someone developing software and building Docker containers who doesn't understand the concept of hidden files? Seems awfully contrived.
The reason app developers think it's fine to dump them in $HOME is because Linux hides them. Those app developers do not bother hiding them on Windows. The specific functionality being used does not 'work just fine everywhere'. It is not the case that Linux functionality is How Computing Works with every deviation being 'out of the way', not even in a hypothetical world where Linux isn't the drastic minority of machines by an order of magnitude.
> Nobody should go out of their way to integrate with Windows APIs
int writeConfigFile(ConfigFile file) {
#if defined(_WIN32)
// Windows-specific function
#elif defined(__linux__)
// Linux-specific function
#elif defined(__APPLE__)
// macOS-specific function
With modern C++, there's probably a way to do this in a nicer manner, and achieve runtime polymorphism with virtual functions or a lambda (function pointer) table.
As another sibling commenter wrote, .NET already has a platform-agnostic function to write to a `user program data` folder that nicely maps to the platform-specific directories. Other GC languages (Java, Go, etc) likely have similar abstractions.
As for scripting... A cross-platform project with scripts that also targets Windows should (in my opinion) have PowerShell `.ps1` scripts accompanying any `.sh` scripts. Better still, scripting should be done in a language that's truly platform-agnostic, like Python.
I'm not sure I'd call that configured well. On Linux, share is supposed to contain static data used by the app, not the changing configuration that normally goes into appdata on Windows. For config the equivalent should be ~/.config/appname
I prefer the app placing the config in the same place on every system. It makes it easier for me to find the file regardless of OS (to modify or back up with a script) and it's simpler for the app dev to write the code for as well.
I recognize this is probably because I first learned about config files on a Unixy system, it's not the "native way" for Windows, and other people have stronger cases for their preference, but this is my preference and I'm stickin to it :)
Your argument breaks down even between 'Unixy' systems. Linux programs that follow the XDG base directory specification write to those, whereas macOS programs tend to write to ~/Library/Preferences or ~/Library/Application Support, neither of which exist on Linux, or even BSDs.
Windows is a lost cause anyway. Even Microsoft products (at a glance: IISExpress, Visual Studio, RDP, Powershell) happily dump their cruft in the Documents folder. I don't know where they imagine users should actually save the files they control.
The difference between Windows ".." and unixy ".." is that the former is done lexically whereas the latter is a link to the canonical parent.
E.g. on Windows: "path\to\..\file" is always the equivalent of "path\file". Whereas on unixy systems "path/to/../file" may take you to a completely different parent directory.
That said, Unix shells can muddy the waters a bit. They may choose to act lexically with some commands.
There are many ways to access the filesystem on Windows. CMD.exe and PowerShell respect `..` to go to the parent directory, as does MSVC C++17 with `std::filesystem`, and .NET, with `System.IO.Path.Combine(String, String)`.
In PowerShell and .NET, there's also the `System.IO.DirectoryInfo.Parent` property, and of course, the equivalent `std::filesystem::path::parent_path` in MSVC C++.
It seems the only official native API for getting the parent directory from a known (full) path is PathCchRemoveFileSpec. But certainly C# and other similar platforms have functions doing similar things, and usually don't require a system API call anyway, it's just string manipulation - unless of course the path is relative to the current directory.
On Windows anyway, the root of the user profile is already filled with garbage directories, and so a few more dot-dirs and files feel par for the course. The advantage is that accessing your root dir is easier than typing out %appdata% in File Explorer.
One could say the same for ~ on Linux. 'It's already bad' isn't an excuse for sloppy programming.
Software should ideally adhere to OS norms. Better still, software shouldn't be opaque about where global/user-specific cache/config data is stored, and should prompt users to choose (or set sane defaults, again adhering to OS norms).
IMO the video game industry is a big offender of home-folder pollution, with saves and configs being splattered all over %USERPROFILE%\Documents, %USERPROFILE%\My Documents\ (which is a legacy holdover from Windows XP), %USERPROFILE%\Saved Games (which does have a corresponding KNOWNFOLDERID), etc etc.
I completely agree! That's why I created this site: https://xdgbasedirectoryspecification.com. We need some place where people can immediately understand the practical benefit, and the minimum ask of their users.
Of course, it doesn't help just to complain about the issue in a void, so I've also submitted like 10 PRs and filed quite a few issues. Projects like pnpm and Poetry took note, and now they comply!
Someone's gotta clean up house, and I don't mind doing the dirty work.
The following programs are for Linux only (The XDG Base Dir Spec isn't inherently followed for MacOS and Windows)
You should fix this. While macOS and its system applications and bundled applications don't adhere to the XDG Base Directory Specification; many programs that run on macOS do.
In fact, almost all of the programs you list run on macOS and (by definition) use the XDG Base Directory Specification. So I would clean that up to not give an incomplete statement.
BTW, the macOS directory structure [1] has been documented since macOS (MacOS X back in the day) shipped in 2001.
Hmm, that's why I said inherent? Because as you mentioned there is a separate macOS directory structure and the system utilities don't follow the specification. Also, the specification is only written for Linux in mind, which is why I said "not inherent for macOS.
The idea for your site is great. A quick suggestion: if you want everyone to immediately understand and sympathize with your cause, then use the tools that everyone knows in your examples. Using some long exa incantation risks alienating people that don't care about things like the latest trendy grep alternative. Just use: `ls -d .*` or `ls -a`
Using some long exa incantation risks alienating people that don't care about things like the latest trendy grep alternative
Exa is the latest, trendy ls alternative.
I don’t think you should remove the Exa example but you certainly should show how to use ls to do something similar for those people still living in the dark ages—ls was created in the 1970s and it hasn’t kept up with the times all that well [1].
I created an ‘ll’ alias for Exa using the Fish shell; obviously you make shell-appropriate aliases in Bash or Z shell:
function ll
exa --color always --long --no-user --no-permissions --all --icons $argv
end
Mainly because it's easier to get people on board when we're keeping a few of the super core dotfiles, especially since those are kind of impossible to change - they are hard coded literally everywhere
Admittedly, the ~/.bashrc etc. files should be there too - but I wanted it to look cleaner :P
A lot of software that does not default to using XDG directories can be coerced into it, usually with environment variables or just manually creating config in a secondary supported XDG location - the arch wiki is the best source of info on that: https://wiki.archlinux.org/title/XDG_Base_Directory
I do not understand the problem with "dot"-files. And I do not understand the benefit to have them in another directory. I think there are more important problems to solve in this world.
Are there more important things to solve? Of course.
However, this particular topic on this particular message board is about dotfiles and the alternatives.
Dotfiles are a clumsy mechanism that came from the early days of Unix.
There are better alternatives that provide the same lack of "unknown/unnecessary" directories and files in the user's home directory/folder.
Each of Windows/MacOS/XDG-compliant OSs has the equivalent of:
1. A configuration directory
2. A storage directory that is maintained between user logins and/or application execution
3. A temporary/cache directory that is not guaranteed to be maintained between user logins or application execution.
The different languages/runtimes also have ways of retrieving these locations which are cross-platform but return the correct values and should be used by all applications that are written to modern standards.
This sounds like “let’s design something nobody ever will use”. Compare how often you (or anyone) created, edited, deleted or backed up a ~/.dotfile vs some file who-tf-knows-where in AppData or Library mazes. These have near zero discoverability and expect-ability.
I've open the project link, scanned the docs, I could not figure out where do find a general description of the problem it tries to solve, and the solution advantages.
You made me curious and didn't deliver ! The anguish !
I think the real culprit here are operating systems and file systems, not programmers (of end-user applications). File systems were designed during an era where semantic meaning was just not important; all file systems cared about (and still care about) are directories and files. The whole paradigm should've been abandoned long ago for something much cleaner.
Please don't. Include the example configuration in your docs (/usr/share/PROG..) and mention it in the manual. Statistically user will have hundreds of apps installed but will only ever customize a small fraction them. So creating config unconditionally on first run is one of the worst contributors to homedir pollution.
Another argument is version upgrades: if you create configur on first run, you forever bake in the set of options present in that version. If later a new option is added, user will have no idea about it.
It's much better to just have a sane implicit default value for each setting when config is not present. Then you can list the default config in your docs or offer a CLI flag --print-default-config or --copy-default-config.
Windows has `%APPDATA%` and `%LOCALAPPDATA%` that are accessible with `ShGetKnownFolderPath`[0], using the appropriate `KNOWNFOLDERID`[1]; all programs should put their configuration and cache data in these paths.
Windows also doesn't know what the dot at the beginning of a file/folder means. Instead, it and NTFS have something that's arguably better: a hidden file attribute `FILE_ATTRIBUTE_HIDDEN`[2], that's again settable/gettable when a file/directory is created or polled, rather than regex-ing for a full-stop.
The worst irony is Microsoft software creating dot-files and dot-dirs on Windows[3][4][5].
[0]: https://learn.microsoft.com/en-us/windows/win32/api/shlobj_c...
[1]: https://learn.microsoft.com/en-us/windows/win32/shell/knownf...
[2]: https://learn.microsoft.com/en-gb/windows/win32/api/fileapi/...
[3]: https://github.com/dotnet/sdk/issues/8678
[4]: https://github.com/OmniSharp/omnisharp-roslyn/issues/953
[5]: https://github.com/microsoft/vscode/issues/3884
For example the folder might look empty but in fact it could contain thousands of hidden files. You want to delete it as it is empty but accidentally delete important system files.
Even worse, imagine if all files on an USB drive are marked as hidden. You see that the drive is empty but when you attempt to copy something to it see a message that there is no free space.
One more example. Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it. It turns out that Windows Explorer which doesn't hide dotfiles is much better for developing projects with Docker!
There should be no hidden files. We cannot do anything with Windows and their MS-DOS legacy but Linux could stop hiding dotfiles in GUI and CLI commands.
The standard Unix folders (usr, var, etc) are also hidden—to be honest, this is a compromise because the Unix filesystem hierarchy sucks, but we are saddled with it for backwards compatibility reasons.
I did appreciate the relative clarity of old macOS systems—everything in the OS was in “System Folder”, the rest of the filesystem was yours, and you could freely move applications without breaking anything, uninstall them by putting them in the trash, etc.
By default, Explorer hides hidden files (and goes one step further and doesn't display file extensions: why???), so do Finder, Dolphin, Nautilus, and even `ls` by default.
> One more example. Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it.
How likely is it that someone is going to want to edit a .env file and not know how to view hidden files?
If a user doesn't know what .ssh/ or .bash_history are, and it can hurt them to accidentally delete or modify them, why show them by default? It's like training wheels on a bike.
>For example the folder might look empty but in fact it could contain thousands of hidden files. You want to delete it as it is empty but accidentally delete important system files.
If it is possible for a regular user to accidentally brick a system like this, it was doomed to begin with. If a user doesn't know what a dotfile is they shouldn't have administrative privileges, and if they do get them there is no safeguard to stop them destroying the system. It's not a dotfile issue.
>Imagine if you have a project and want to edit an .env file. But as dotfiles are hidden in Linux you don't see this file and cannot open it. It turns out that Windows Explorer which doesn't hide dotfiles is much better for developing projects with Docker!
In what reality is someone developing software and building Docker containers who doesn't understand the concept of hidden files? Seems awfully contrived.
As another sibling commenter wrote, .NET already has a platform-agnostic function to write to a `user program data` folder that nicely maps to the platform-specific directories. Other GC languages (Java, Go, etc) likely have similar abstractions.
As for scripting... A cross-platform project with scripts that also targets Windows should (in my opinion) have PowerShell `.ps1` scripts accompanying any `.sh` scripts. Better still, scripting should be done in a language that's truly platform-agnostic, like Python.
Deleted Comment
I recognize this is probably because I first learned about config files on a Unixy system, it's not the "native way" for Windows, and other people have stronger cases for their preference, but this is my preference and I'm stickin to it :)
When in Rome, do as the Romans do.
That is impossible because in Linux there is no drive letters and you cannot have the same path to a file as in Windows.
E.g. on Windows: "path\to\..\file" is always the equivalent of "path\file". Whereas on unixy systems "path/to/../file" may take you to a completely different parent directory.
That said, Unix shells can muddy the waters a bit. They may choose to act lexically with some commands.
Unless an app uses \\?\ prefixes and special API for navigation, which is rare, ime.
There are many ways to access the filesystem on Windows. CMD.exe and PowerShell respect `..` to go to the parent directory, as does MSVC C++17 with `std::filesystem`, and .NET, with `System.IO.Path.Combine(String, String)`.
In PowerShell and .NET, there's also the `System.IO.DirectoryInfo.Parent` property, and of course, the equivalent `std::filesystem::path::parent_path` in MSVC C++.
Software should ideally adhere to OS norms. Better still, software shouldn't be opaque about where global/user-specific cache/config data is stored, and should prompt users to choose (or set sane defaults, again adhering to OS norms).
IMO the video game industry is a big offender of home-folder pollution, with saves and configs being splattered all over %USERPROFILE%\Documents, %USERPROFILE%\My Documents\ (which is a legacy holdover from Windows XP), %USERPROFILE%\Saved Games (which does have a corresponding KNOWNFOLDERID), etc etc.
Of course, it doesn't help just to complain about the issue in a void, so I've also submitted like 10 PRs and filed quite a few issues. Projects like pnpm and Poetry took note, and now they comply!
Someone's gotta clean up house, and I don't mind doing the dirty work.
You should fix this. While macOS and its system applications and bundled applications don't adhere to the XDG Base Directory Specification; many programs that run on macOS do.
In fact, almost all of the programs you list run on macOS and (by definition) use the XDG Base Directory Specification. So I would clean that up to not give an incomplete statement.
BTW, the macOS directory structure [1] has been documented since macOS (MacOS X back in the day) shipped in 2001.
[1]: https://developer.apple.com/library/archive/documentation/Fi...
Is there an exact phrasing you would prefer?
Exa is the latest, trendy ls alternative.
I don’t think you should remove the Exa example but you certainly should show how to use ls to do something similar for those people still living in the dark ages—ls was created in the 1970s and it hasn’t kept up with the times all that well [1].
I created an ‘ll’ alias for Exa using the Fish shell; obviously you make shell-appropriate aliases in Bash or Z shell:
[1]: https://the.exa.website/introductionDeleted Comment
I.e. if it's empty, or if the first character is not a forward slash, then use the default?
Admittedly, the ~/.bashrc etc. files should be there too - but I wanted it to look cleaner :P
Dotfile madness - https://news.ycombinator.com/item?id=19063727 - Feb 2019 (514 comments)
However, this particular topic on this particular message board is about dotfiles and the alternatives.
Dotfiles are a clumsy mechanism that came from the early days of Unix.
There are better alternatives that provide the same lack of "unknown/unnecessary" directories and files in the user's home directory/folder.
Each of Windows/MacOS/XDG-compliant OSs has the equivalent of:
1. A configuration directory 2. A storage directory that is maintained between user logins and/or application execution 3. A temporary/cache directory that is not guaranteed to be maintained between user logins or application execution.
The different languages/runtimes also have ways of retrieving these locations which are cross-platform but return the correct values and should be used by all applications that are written to modern standards.
There are better alternatives
Let’s define “better” first.
https://github.com/nix-community/home-manager
https://news.ycombinator.com/item?id=33311958
You made me curious and didn't deliver ! The anguish !