174 lines
14 KiB
Plaintext
174 lines
14 KiB
Plaintext
# Regarding hier(7) in $HOME
|
|
|
|
Taking a look at hier(7) is a valuable way to understand how your Unix-like system is structured. It tells you exactly what each directory on your filesystem does, so you always know exactly where to put system files.
|
|
|
|
## The Hierarchy for System Files
|
|
Taking a look at the overall structure, you may notice that a lot of directory names seem to be repeated, but in different locations. You'll also notice that these directories seem to be structured roughly the same way the / directory is. For example, you have /bin/, /usr/bin/, and /usr/local/bin/.
|
|
|
|
On my Arch Linux install, according to hier(7):
|
|
* / is for critical utilities required to boot and repair the system
|
|
* /usr/ is the main place system files get installed to, including all of the programs installed by the package manager
|
|
* /usr/local/, to my understanding, is where you'd place system files that you compiled and installed manually, rather than using the package manager
|
|
=> https://man.archlinux.org/man/hier.7 View Arch Linux's hier(7) online
|
|
|
|
On FreeBSD, according to hier(7), the equivalent directories are as follows:
|
|
* / is essentially the same as on Arch Linux
|
|
* /usr/ seems to be for core operating system files that aren't required for boot or repair
|
|
* /usr/local/ is for system files not part of the core operating system, such as package files or locally-compiled programs
|
|
=> https://man.freebsd.org/cgi/man.cgi?hier(7) View FreeBSD's hier(7) online
|
|
|
|
As you can see, there seem to be three separate ""root"" directories, each one with a specific purpose. However, these aren't the only three directories that seem to be root directories. The /root/ and /home/$USER/ directories, which act as user home directories, ALSO seem to be root directories, but its nearly impossible to tell at first, because they use an entirely different set of directories.
|
|
|
|
## The Hierarchy for User Files
|
|
The user's home directory follows its own hierarchy conventions completely unlike any of the aforementioned system tree hierarchies. Even worse, the home directory makes extensive use of dotfiles, which are an unintended bug that's most often leveraged by lazy programmers who don't want to learn how the system they're programming on works.
|
|
=> dotfiles-rob-pike.gmi Rob Pike on Dotfiles
|
|
|
|
The home directory tree as compared to the system tree:
|
|
* ~/.config/, as opposed to /etc/
|
|
* ~/.cache/, as opposed to /var/cache/
|
|
* ~/.local/bin/, as opposed to /bin/
|
|
* ~/.local/share/, as opposed to /share/
|
|
* ~/.local/state/, as opposed to /var/lib/
|
|
=> https://specifications.freedesktop.org/basedir-spec/latest/ XDG Base Directory Specification
|
|
|
|
As you can see, the user's home directory has all of the same data as any of the system trees, but with completely different names, all leveraging the dotfile bug. Perhaps I would've been fine if the files made use of the usual names, but were all placed in ~/.local/, because then it'd just mean the tree root isn't at ~/, but at ~/.local/, but this isn't the case.
|
|
|
|
Even worse, even though all of these directories can be moved using $XDG_*_HOME variables, an incredible number of programs completely ignore the XDG Base Directory Specification, and hardcode the path, or place their files straight into ~/, completely ignoring any standard directories, with no possible way to change it. Some of these programs think they're so special that they even refuse to consider this a bug, like OpenSSH with ~/.ssh/.
|
|
=> https://wiki.archlinux.org/title/XDG_Base_Directory#Hardcoded Arch Wiki's list of hardcoded dotfiles
|
|
=> https://web.archive.org/web/20190925004614/https://bugzilla.mindrot.org/show_bug.cgi?id=2050 OpenSSH bug report
|
|
|
|
To finish off talking about the home directory tree, we can't forget to mention the XDG User Directories:
|
|
* ~/Downloads/
|
|
* ~/Desktop/
|
|
* ~/Documents/
|
|
* ~/Music/
|
|
* ~/Pictures/
|
|
* ~/Public
|
|
* ~/Templates/
|
|
* ~/Videos/
|
|
=> https://wiki.archlinux.org/title/XDG_user_directories Arch Wiki's page on XDG User Directories
|
|
|
|
Honestly, other than the fact that they use capital letters, which is a personal preference thing, I can't really complain about these. I'd prefer them somewhere else, but the xdg-user-dirs tool combined with $XDG_CONFIG_HOME/user-dirs.dirs lets me move and rename them, which most programs do actually seem to respect.
|
|
|
|
The main point here is that system files have THREE locations that have the exact same directory structure, but user files aren't the same. You can't leverage existing knowledge to know where to put user files, and programs have to handle user files as an entirely separate case from system files. The directory structure CAN be changed, but not all programs respect those changes, and some completely ignore the structure to begin with, which seems to be caused predominantly due to a specific bug allowing lazy programs to shove files wherever they want with the knowledge that those files will be ""hidden"" and thus not a bother.
|
|
|
|
## My Current Home Directory Setup
|
|
With all this said, I decided to make use of what I could in order to make my home directory mimic the structure of the system trees, as well as to stop making use of dotfiles as hidden directories.
|
|
|
|
### Unhiding Dotfiles
|
|
This one was pretty simple. All I really had to do is add to my ~/.shrc:
|
|
```
|
|
alias ls="ls -A"
|
|
```
|
|
I also added to my $XDG_CONFIG_HOME/ranger/rc.conf for the ranger file manager:
|
|
```
|
|
set show_hidden true
|
|
```
|
|
|
|
### Undotting My Dotfiles
|
|
This predominantly involved adding a bunch of variables to my ~/.profile:
|
|
```
|
|
## Add /bin for executables instead of .local/bin
|
|
PATH="${PATH}:${HOME}/bin"
|
|
|
|
## Should replace .config, .cache, and .local/{share,state} for most programs
|
|
XDG_CACHE_HOME="${HOME}/var/cache"; export XDG_CACHE_HOME
|
|
XDG_CONFIG_HOME="${HOME}/etc"; export XDG_CONFIG_HOME
|
|
XDG_STATE_HOME="${HOME}/var/lib"; export XDG_STATE_HOME
|
|
XDG_DATA_HOME="${HOME}/share"; export XDG_DATA_HOME
|
|
|
|
## These programs think they're special and should go to hell
|
|
## but they give me an option at all which I appreciate
|
|
### Bash
|
|
HISTFILE="${XDG_STATE_HOME}/bash/history"; export HISTFILE
|
|
|
|
### Python (>3.12)
|
|
PYTHON_HISTORY="${XDG_STATE_HOME}/python/history"; export PYTHON_HISTORY
|
|
PYTHONPYCACHEPREFIX="${XDG_CACHE_HOME}/python"; export PYTHONPYCACHEPREFIX
|
|
PYTHONUSERBASE="${XDG_DATA_HOME}/python"; export PYTHONUSERBASE
|
|
```
|
|
|
|
### Moving Desktop Files
|
|
As mentioned earlier, the xdg-user-dirs tool in combination with $XDG_CONFIG_HOME/user-dirs.dirs achieves what I want:
|
|
```
|
|
XDG_DESKTOP_DIR="$HOME/tmp"
|
|
XDG_TEMPLATES_DIR="$HOME/tmp"
|
|
XDG_PUBLICSHARE_DIR="$HOME/tmp"
|
|
XDG_DOWNLOAD_DIR="$HOME/tmp"
|
|
|
|
XDG_PICTURES_DIR="$HOME/media/img"
|
|
XDG_DOCUMENTS_DIR="$HOME/media/doc"
|
|
XDG_MUSIC_DIR="$HOME/media/audio"
|
|
XDG_VIDEOS_DIR="$HOME/media/video"
|
|
```
|
|
|
|
This one probably needs some explaining.
|
|
|
|
To start, the hier(7) manpage says that /media/ is meant for removable media, like CDs or floppy disks, with a subdirectory for each type of media (i.e. /media/floppy[0-9]/), which clearly isn't quite what I'm using it for here. However, to begin with, I normally only use /mnt/ to mount external drives, but I COULD see myself mounting an external drive dedicated specifically to hosting my media files at ~/media/, if I'd been a desktop user. Of course, I'm also forgoing the media type subdirectories, which I do because I can only see myself mounting multiple drives here under the condition that its a single LVM or ZFS pool. Essentially, I'm bending the meaning of ~/media/ here to OPTIONALLY mean "removable media", and more predominantly mean "media files".
|
|
|
|
It might also seem weird that I listed so many of them at ~/tmp/, but hear me out here. For one, I don't have a desktop, since I use a tiling window manager, and I have zero clue what the templates or public share directories are for, so I combined these all into my downloads directory to act as a large catch-all for any file I'm not immediately sure should go elsewhere. The reason I put these in ~/tmp/ specifically, though, is because I've found that the only files that remain in my downloads directory for a long time tend to be those that I really only needed once for a particular purpose, such as a Linux ISO image to write to a USB drive. Thus, I've actually gone so far as to add the following to my /etc/fstab:
|
|
```
|
|
tmpfs /home/snit/tmp tmpfs rw,relatime 0 0
|
|
```
|
|
Which, of course, means that my ~/tmp/ directory will be cleared every time I reboot; this may seem inconvenient to some, so I don't recommend this part, but, again, I only use this directory for files I'm probably gonna delete soon anyways.
|
|
|
|
### Issues I've Encountered
|
|
The main issue I have is just with software that doesn't follow the specifications properly. OpenSSH places files in ~/.ssh/, Firefox has ~/.mozilla/ (I'm told this will soon be fixed), and it seems that changing settings in Firefox's filechooser dialogue causes a file to be created at ~/.config/dconf/user, even though dconf claims to support $XDG_CONFIG_HOME.
|
|
|
|
There's also ~/.profile and ~/.shrc. I can move the latter using ENV, but the former to my knowledge simply can't be moved. However, I've opted to leave both as is and accept them, simply because FreeBSD seems to put similar files straight into /, so it technically has the consistency I'm looking for here, even if its slightly inelegant.
|
|
|
|
### Directory Structure
|
|
Currently this is what my home directory looks like:
|
|
* ~/bin/ for local scripts and executables (replaces ~/.local/bin/)
|
|
* ~/etc/ for configuration files (replaces ~/.config/)
|
|
* ~/media/ for media files like images or documents
|
|
* ~/media/audio for audio files
|
|
* ~/media/video for video files
|
|
* ~/media/img for images (this actually contains a lot of videos for convenience, but I might change that)
|
|
* ~/media/doc for text-based files like PDF documents and personal notes
|
|
* ~/mnt/ as an alternative to /mnt/ for easier access
|
|
* ~/share/ for architecture-agnostic data (replaces ~/.local/share/); this is actually where I put my desktop wallpapers
|
|
* ~/src/ for program source code
|
|
* ~/src/foreign/ for code I didn't write for organisation purposes (might also add ~/src/local/)
|
|
* ~/tmp/ for the default download directory, mounted as a tmpfs
|
|
* ~/var/cache/ for cache data (replaces ~/.cache/)
|
|
* ~/var/lib/ for state data (replaces ~/.local/state)
|
|
* ~/.mozilla/ for Firefox data (can't move)
|
|
* ~/.ssh/ for OpenSSH data (can't move)
|
|
* ~/.profile for my shell profile (can't move)
|
|
* ~/.shrc for my interactive shell settings
|
|
|
|
## Conclusion
|
|
Mainly I just wish user directory trees worked similar to system trees. Why can't we leverage existing knowledge for this? Why do I have to write special cases based on whether its a system or user tree? Why can't programs just follow standards properly?
|
|
|
|
It'd be cool if, for example, I could actually compile a package and install it to my user directories just the same as if I were installing it to the system itself. In conjunction with Plan 9's bind(1), I could see this being genuinely useful on multi-user systems like pubnixes. After all, I can download, compile, and run that program regardless, so, in my opinion, there's no real point in NOT giving me the option to use the package manager in my own home directory.
|
|
|
|
Anyways, that's all I've got for now. If you've any questions or feedback on this admittedly incredibly cursed and controversial topic, I'd love to hear it:
|
|
=> mailto:snit@cock.li Email
|
|
=> https://matrix.to/#/@snit:isekai.rocks Matrix
|
|
|
|
|
|
## Addendum I
|
|
Just wanted to add that I no longer mount ~/tmp/ as a tmpfs. It honestly works fine for the most part, but I had transmission set to download incomplete torrents to ~/tmp/ before moving them to ~/media/ when finished, which gave me a lot of out-of-memory errors if I downloaded a large enough torrent, or a lot of torrents at once.
|
|
|
|
Also, I use trash-cli and have rm aliased to it. When ~/tmp/ is mounted as a tmpfs, it actually gets its own ~/tmp/.Trash/ directory, as its a different filesystem from /home. Its not a big deal but its somewhat annoying having two separate trash directories. And if you haven't figured it out already from uh everything above this, annoyances when it comes to directories are intolerable on my system.
|
|
|
|
So I don't mount it anymore, and instead just use it as a regular directory that I clear out sometimes. The only real benefit it used to bring was clearing out automatically on shutdown, but I could probably just add an rm line to my .profile for a similar effect.
|
|
|
|
## Adendum II
|
|
I've made a couple more changes since the last update.
|
|
|
|
First, I've updated my ~/.profile to work similarly to Arch's /etc/profile, which actually outsources most of its work to files in /etc/profile.d/. I've opted to do the same thing, with specific files for my XDG Base Directory compliance, and for setting other variables related to Wayland or fcitx5. Since I'd put most of ~/.profile in ~/etc/, and ~/.shrc can be put literally anywhere (as it's set by $ENV), I've opted to move it to ~/etc/sh/shrc. This reduces my total number of cringe noncompliant dotfiles in $HOME to three.
|
|
|
|
The other change that I've made is the addition of ~/libexec/ and ~/sbin/, which I think are truly underutilised directories even in the system hierarchies (Arch foregoes them entirely in favour of just using /bin/ and /lib/).
|
|
|
|
I use ~/libexec/ for anything I'd normally put in ~/bin/, but that I'd rarely, if ever, run directly. Most of these are scripts related to setting up my window manager, and are thus only ever executed by my window manager. There's also one that I have run at shell startup, which prints every dotfile that clutters my home directory, and automatically deletes all dotfiles in a specified list (only deleting what I know I don't care about). I mostly added ~/libexec/ because I've been thinking of ways to keep my $PATH namespace less cluttered, and this is something easy to implement AND quite elegant in my opinion.
|
|
|
|
I don't actually use ~/sbin/ on my home systems. There's only one script I use at home that needs to be run as root, and it's run by my window manager, so I've opted instead to just give it a nopass option in my /etc/doas.conf, and place it in ~/libexec/. On isekai.rocks, though, I do actually use ~/sbin/. The main two scripts I use in ~/sbin/ are one to sync the live isekai.rocks capsule to the git repository, and another to set up a new user account on the pubnix. There was also previously one that updated Minecraft mods, automatically creating new zip files for download, and restarting the server to load the new mods.
|
|
|
|
So, to recap, the changes I've made since the original post were:
|
|
* Stop mounting ~/tmp/ as a tmpfs
|
|
* Move ~/.shrc to ~/etc/sh/shrc
|
|
* Create ~/libexec/
|
|
* Create ~/sbin/
|