If I introduce an alias (like `grep='grep --binary-files=without-match --ignore-case --color=auto`) that matches the name of a system binary - I probably do that intentionally.
And if I EVER need to call grep without my alias - I just prefix it with a backslash: \grep will search with case sensitivity and no color and will scan binaries.
Yes, I can do path ordering to override usual commands. However, having a set of odd-job scripts which start with a comma gives a nice namespacing capability alongside a well narrowed-down tab-completion experience.
While it's not the neatest thing around, it works surprisingly well.
Another idea which looks useless until you start using is text expanders (i.e.: Espanso and TextExpander).
I've never had this collision problem yet, despite appending my script directory to the end, but I'll use either of the above solutions if that ever becomes a problem.
Btw on the second suggestion, I think there's a command named `command` that can help with that sort of thing, avoids recursive pitfalls.
Don't tell people to sacrifice agency for apocalypse insurance that doesn't work, lol
And then there’s Claude. It deletes whatever it finds at ~/.local/bin/claude, so I have to use a shell function instead to invoke the full path to my wrapper.
alias claude="sandbox-exec -f ~/agents-jail.sb ~/.local/bin/claude --dangerously-skip-permissions"Because I cannot imagine much 3rd party scripts working with random flags added to core tools
Random flags added to core tools are done with aliases, which do not affect the launched processes, not by shadowing them in ~/bin. Shadowing in ~/bin are for cases where a newer (compared to the system-wide version) or custom version of a tool is needed.
* https://news.ycombinator.com/item?id=40769362 (2024, 169 comments)
* https://news.ycombinator.com/item?id=31846902 (2022, 123 comments)
* https://news.ycombinator.com/item?id=22778988 (2020, 90 comments)
You put keyseqs in ~/.inputc, set a keyseq-timeout, and it just works.
I do something similar with my personal scripts — prefix them with a short namespace. The real win isn't just avoiding collisions though, it's tab completion. Type the prefix and tab, and you immediately see all your custom stuff without wading through hundreds of system commands.
The 2009 date on this is wild. Some of these simple unix conventions age better than most frameworks.
Every tool and shell that lay in arm's reach treated the comma as a perfectly normal and unobjectionable character in a filename.
WTF. After 40 years maybe I should have figured that one out.I see Bash only uses commas in Brace expansions:
file{1,2,3}.txt # file1.txt file2.txt file3.txt
I guess it would only be a problem if you want to expand
file,.txt
file,,.txt
file,,,.txtI snapshot my entire home directory every hour (using btrfs+snapper), but I exclude ~/.local/ from the snapshots. So I use ~/.local/bin/ for third-party binaries, since there's no reason to back those up; and ~/bin/ for scripts that I wrote myself, since I definitely want to back those up.
This is a pretty idiosyncratic use though, so I'd be surprised if many other people treated both directories this way.
(Anything that modifies standard behaviour is not in PATH, but instead a shell function present only in interactive shells, so as not to break scripts.)
Unix lore: Early unix had two-letter names for most common names to make them easy to type on crappy terminals, but no one* letter command names because the easier were reserved for personal use.
I thought was for mixin externally provided systems like Homebrew, local is for machine or org-level customizations, and ~ is for user-level customizations.
The advantage of /opt is that multi-file software stays together. The disadvantage is that PATHs get long.
It kind of goes against the idea why dotfiles are dot-prefixed.
~/.local was only invented around 2003 and gained widespread usage maybe 15 years or so ago...
People used ~/bin already in the 90s ;-)
I started using a prefix because I like very short script names that are easy to type
I prefer giving scripts numbers instead of names
Something like "[number"
I use prefixes and suffixes to group related scripts together, e.g., scripts that run other scripts
I have an executable directory like ~/bin but it's not called bin. It contains 100s of short scripts
Neat trick! I don’t think I’ll namespace everything this way, because there’s some aliases and commands I run so often that the comma would get annoying, but for other less frequently used helper scripts then this will be perfect!
This convention was suggested by the GNU Arch version control system years ago (maybe 20??), but it's really useful for the same tab completion reason and I have kept it for almost two decades, even when I switched to git.
File names or directories starting with a comma where considered “junk”, and ones with a plus sign I think where considered “precious”.
I create a home directory "x" for executables that I want to manage as files, and don't want on PATH or as alias.
To run foo: ~/x/foo
For example I have GNU date as ~/x/date so it's independent of the system BSD date.
If we want to stay within (lowercase) alphabetic Latin characters I think prefixing with the least common letters or bigrams that start a word (x, q, y, z, j) is best.
`y' for instance only autocompletes to `yes' and `ypdomainname' on my path.
Choosing a unique bigram is actually quite easy and a fun exercise.
And we can always use uppercase Latin letters since commands very rarely use never mind start with those.
Then again, I don't really believe in performing complex operations manually and directly from a shell, so I don't really understand the use-case for having many small utilities in PATH to begin with.
Also, kudos to keeping it so concise and to the point, thats some prime writing.
I have a command named "decolour", which strips (most) ANSI escape codes. Clear as day what it does, almost nobody uses this spelling when naming commands that later land as part of a distribution.
On my most frequently used machine/dev env this means -
e for vim
m for mise
n for pnpm
c for Claude
x for codex
j for just
I use fish abbreviations for this, as they expand to the full command in the shell history.
quick, easy and consistent. entirely voluntary.
Bravo
Off-topic: What the hell is that font on this website? And why does the "a" look like that?
It went weird pretty quickly...
It is objectively cleaner to keep your user scripts in your home, that way they are only in _your_ PATH, whereas putting them in /usr/[local/]bin implicitly adds them to every [service] user on the machine, which I can see creating obscure undesired effets.
Not even mentioning the potential issues with packages that could override your scripts at install, unexpected shadowing of service binaries, setuid security implications, etc.
I'd prefer to use underscore (when writing BASH scripts, I name all my local variables starting with underscore), but a simple two or three letter prefix would also work. I don't like the idea of a punctuation prefix as punctuation usually has a specific meaning somewhere and including it as the first character in a filename looks wrong. (e.g. Comma is typically used as a list separator and it's a bit of cognitive dissonance to see it not used in that context)
> I don't like the idea of a punctuation prefix as punctuation usually has a specific meaning somewhere and including it as the first character in a filename looks wrong.
So you don’t use dotfiles? ;)
I'm not convinced by "quicker to type" arguments as that's rarely the bottleneck, so I'm perfectly happy with using underscores in filenames and variables. I wouldn't use underscore as the beginning character of a filename unless it had a specific meaning to me (e.g. temporary files), so I'd be more inclined to use a two or three character prefix instead.
Nowadays, I tend to skip using a personal prefix and just try to name commands with a suitable verb in front (e.g. "backupMySQL") and ensure that there's no name collisions.
`.local/bin` seems to be much more common in my experience for this use case. And for good reason.
2024: https://news.ycombinator.com/item?id=40769362