[HN Gopher] Start all of your commands with a comma (2009)
___________________________________________________________________
Start all of your commands with a comma (2009)
Author : theblazehen
Score : 528 points
Date : 2026-02-04 19:59 UTC (3 days ago)
(HTM) web link (rhodesmill.org)
(TXT) w3m dump (rhodesmill.org)
| sevg wrote:
| This is one of those ideas that is so simple and elegant that it
| makes you think "why did I never think of doing this?!"
|
| 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!
| pjerem wrote:
| Maybe then try ending your commands with a comma so that you
| don't break first-char autocomplete !
| stavros wrote:
| But that's the killer feature for me! I always forget the
| little commands I've written over the years, whereas a
| leading comma will easily let me list them.
| bonzini wrote:
| I do something similar with build trees, naming them +build,
| +cross-arm etc.
|
| 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.
| amszmidt wrote:
| It was suggested by Tom Lord (RIP), who used it heavily long
| before he wrote GNU Arch.
|
| File names or directories starting with a comma where
| considered "junk", and ones with a plus sign I think where
| considered "precious".
| dadandang wrote:
| ,Start all of _your_ commands with a comma
| zdc1 wrote:
| Should be titled _Prefix your script names with a comma_.
| Current title is a little clickbait-y through its ambiguity.
| albert_e wrote:
| Agree.
|
| I thought the title meant I should type ,ls instead of ls.
| JamesTRexx wrote:
| ,sudo make me a sammich
|
| Like so?
| bronlund wrote:
| This is just brilliant. Thanks.
| falloutx wrote:
| Finally a post that is relevant to what I have been looking for
| quite some time.
|
| Also, kudos to keeping it so concise and to the point, thats some
| prime writing.
| luplex wrote:
| similarly, I start all my underscorends with an underscore
| guilherme-puida wrote:
| (2009)
| HelloUsername wrote:
| Previous discussions:
|
| 2024: https://news.ycombinator.com/item?id=40769362
|
| 2022: https://news.ycombinator.com/item?id=31846902
|
| 2020: https://news.ycombinator.com/item?id=22778988
| mathfailure wrote:
| I didn't like the idea. I prefer the alternative approach: _I_
| decide the order of dirs in the PATH env. If I introduce an
| executable with a name, that overrides a system one - I probably
| do that intentionally.
|
| 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.
| chrisjj wrote:
| > If I introduce an executable with a name, that overrides a
| system one
|
| ... and breaks existing scripts that reference the system one,
| right?
| amszmidt wrote:
| Not if it is an alias.
| hk__2 wrote:
| But yes if it's another executable.
| fragmede wrote:
| curious if you're customizing anyway, why not use eg ripgrep?
| llimllib wrote:
| Not OP, but I use ripgrep and customize it with an alias as
| well, so it applies equally there
| wtetzner wrote:
| repgrep's CLI options and general behavior are different from
| grep. I tend to use both for different things.
| mathfailure wrote:
| Others have already given valid answers: grep is not ripgrep
| [their params don't match], so it's a bad idea to alias
| 'grep' to use ripgrep. But it's okay to alias 'ripgrep' (or
| 'rg' or whatever) to use ripgrep with some args.
| 112233 wrote:
| Any severe side effects so far? Have you set PATH up somehow so
| it is effect only on interactive prompt, and not in the
| launched processes?
|
| Because I cannot imagine much 3rd party scripts working with
| random flags added to core tools
| deredede wrote:
| I also do this.
|
| 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.
| mathfailure wrote:
| Not really, since if one usually does that - they probably
| understand the possible consequences and don't shadow
| whatever they like, but do it carefully.
|
| On MacOS I shadow that way just curl and git binaries to the
| versions installed from homebrew and nothing has broken
| (yet). I know that tar on MacOS is also a weirdo that I'd
| rather shadow with the homebrew's gtar, but their args are
| different and I of course understand that there's a high
| probability of something in system to be bound to mac's
| version of tar, so here I better remember to use 'sane' tar
| as gtar or use an alias (instead of shadowing the binary) for
| tar to use gtar (because aliases are for users, not for
| system scripts/processes).
|
| And on my home desktop's Debian - I don't even use shadowing
| of binaries at all (never needed it).
|
| Also, I just realized: I change PATH env via my shell's rc
| script (~/.zshrc), so I probably could worry even less about
| shadowing system binaries (like tar on MacOS) possibly
| breaking things.
| mid-kid wrote:
| Either adding your script directory in front of the PATH, or
| creating `alias` that provide a full path to your script where
| a conflict exists, makes a whole lot more sense to me.
|
| 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.
| mathfailure wrote:
| One rarely actually needs to shadow binaries. Some cases
| could indeed be covered by introducing an alias that binds
| the binary's name to call a different copy of that binary.
|
| You use shadowing to fix issues where you install some
| software that expects you to have a sane and ~recent version
| of some tool like git, but you don't as your system provides
| that binary and unfortunately it is either not sane (not
| GENERALLY sane [while it could be sane for system scripts])
| or not recent enough. In that case the program's function
| would simply fail if it would call the system's binary and
| you shadow the binary with your version to fix that.
|
| > adding your script directory in front of the PATH
|
| That's a poor advice for the scripts you call relatively
| frequently. Instead, (as a general approach, we aren't
| discussing some particular script) don't use shadowing for
| scripts: just pick a non-conflicting script name and append
| the script's dir to $PATH.
| Joker_vD wrote:
| > That's a poor advice for the scripts you call relatively
| frequently.
|
| Why? It protects you from someone else ( _cough_ updated
| packages introducing new commands _cough_ ) picking a name
| you already use.
| mathfailure wrote:
| Because it's useless extra typing. People try to narrow
| commands down to two fucking chars and you suggest to
| type the whole goddamn path!
| alsetmusic wrote:
| From my own aliases: alias
| curl='/opt/homebrew/opt/curl/bin/curl ' alias rsync-
| copy='/opt/homebrew/bin/rsync -avz --progress -h '
| alias rsync-move='/opt/homebrew/bin/rsync -avz --progress -h
| --remove-source-files ' alias rsync-
| synchronize='/opt/homebrew/bin/rsync -avzu --delete
| --progress -h ' alias rsync-
| update='/opt/homebrew/bin/rsync -avzu --progress -h '
| alias vi='/opt/homebrew/bin/vim -S ~/.vimrc' alias
| vim='/opt/homebrew/bin/vim -S ~/.vimrc' alias
| wget='/opt/homebrew/bin/wget -c '
|
| There are others with flags added. These are the ones that
| override the builtin MacOS versions that aren't up-to-date.
| alance wrote:
| Just on your first suggestion, this also means that if a person
| or process can drop a file (unknown to you) into your ~/bin/
| then they can wreak havoc. Eg they can override `sudo` to
| capture your password, or override `rm` to send your files
| somewhere interesting, and so on.
|
| Btw on the second suggestion, I think there's a command named
| `command` that can help with that sort of thing, avoids
| recursive pitfalls.
| znpy wrote:
| While true, what you describe is very unlikely to happen and
| most definitely won't happens on systems where i'm the only
| users.
| functionmouse wrote:
| That would require someone to already want to sabotage me in
| particular, learn my private workflows, and also have write
| access to my home folder. At that point, All is Lost.
|
| Don't tell people to sacrifice agency for apocalypse
| insurance that doesn't work, lol
| latexr wrote:
| If someone can drop a file in your ~/bin, they can also edit
| your shell's startup files to add their malicious command.
| wtetzner wrote:
| I think it's already game over if they have access to your
| home directory. They can also edit your path at that point.
| dieulot wrote:
| The issue of rootless malicious command overrides is solved
| by typing the whole path, such as "/bin/sudo".
| mathfailure wrote:
| No, don't do that as a precaution. As others have already
| answered correctly - it's too late to worry about such
| things if a malicious agent has write access to your
| ${HOME} dir.
| CGamesPlay wrote:
| I do this, and routinely shadow commands with my own wrappers
| to do things like set environment variables.
|
| 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.
| e1g wrote:
| You can use an alias, which takes priority over $PATH. e.g. I
| have this in .zhsrc to override the "claude" executable to
| run it in the OS sandbox: alias
| claude="sandbox-exec -f ~/agents-jail.sb ~/.local/bin/claude
| --dangerously-skip-permissions"
| plagiarist wrote:
| How does your sandbox ruleset look? I've been using
| containers on Linux but I don't have a solution for macOS.
| e1g wrote:
| Here's my ruleset https://gist.github.com/eugene1g/ad3ff9
| 783396e2cf35354689cc6...
|
| My goal is to prevent Claude from blowing up my computer
| by erasing things it shouldn't touch. So the philosophy
| of my sanboxing is "You get _write access_ to $allowlist,
| and _read access_ to everything except for $blocklist ".
|
| I'm not concerned about data exfiltration, as
| implementing it well in a dev tool is too difficult, so
| my rules are limited to blocking highly sensitive folders
| by name.
| icedchai wrote:
| That's neat. I'm going to base my ruleset off of yours.
| I've been messing around with claude more and more lately
| and I need to do _something._
| pmarreck wrote:
| I do the same thing, but I also have a command that shows me
| what functions or scripts might be shadowing other scripts
| e40 wrote:
| Care to share?
| cluckindan wrote:
| which <commandname>
| e40 wrote:
| Seemed like it was more than that, but the comment is
| ambiguous. I took it to mean "show me all the commands
| which are shadowed" not "is this command shadowed"...
| lowmagnet wrote:
| the sibling answer but with `-a` before command name, will
| display all path hits for a command.
| bayindirh wrote:
| Looked so backwards to me, too. However, I decided to give it a
| go, anyway. Now, I have some scripts and small commands which
| start with a comma, and it looks neat and time saving.
|
| 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).
| xbryanx wrote:
| Love Alfred Snippets for this same text expander need.
| mathfailure wrote:
| I never knew that what I've known as 'hotstrings' (since the
| AutoHotKey days) other sometimes also call 'text expanders'.
| aschla wrote:
| The irony in the number of extra commas you've used in this
| comment...
| bayindirh wrote:
| As a non-native English speaker and writer/typer I'm not
| well versed in usage of commas unfortunately.
|
| Feel free to add the required ones while reading this
| comment.
|
| Sorry for the inconvenience this might create.
| mh- wrote:
| As a native speaker the original comment seemed
| completely fine, ignore them. Also, I never would never
| guessed that you weren't also a native English speaker.
| tempestn wrote:
| Agreed. The commas before the sentence-ending 'too' and
| 'anyway' were perhaps slightly unusual, but not enough so
| that I even noticed them, and I don't think either is
| incorrect. All the rest were perfectly normal.
| ri0t wrote:
| TIL: Backslash overrides alias - wow!
|
| Thanks, mathfailure - this genuinely improves my life!
| mixmastamyk wrote:
| 'command grep' also works in several shells. A little longer
| but looks good in scripts etc.
| wasmainiac wrote:
| I would recommend against overriding standard system binaries,
| you could break compatibility on your system with scripts that
| depend on those binaries. I just use an abbreviation like
| rg="grep -RE"
| RadiozRadioz wrote:
| Why are those scripts running in interactive login shells? If
| they are influenced by the configuration of profile, then the
| scripts are bad.
| wasmainiac wrote:
| That's true, but I would still call overloading system
| binaries bad practice. Your making yourself foot gun.
| mathfailure wrote:
| No, in fact he is correct: system scripts won't pick up
| your overrides configured via your shell's rc scripts.
| wasmainiac wrote:
| I said he was right, but in your case you are wrong. Your
| shell loads thr profile script for login shells, but will
| load your bashrc regardless of login or not
|
| Excluding this argument, overloading system commands is
| still bad practice lol. Have you ever logged into an
| embedded device and had a busy box environment? the
| behaviour of some utilities can be different from what
| you expect for utilities of the same name.
| hinkley wrote:
| When "I" means me then this usually works for me. But when "I"
| becomes "we", sometimes this goes off the rails because someone
| introduces a bin with breaking changes that silently fucks up
| projects that dev doesn't really know about, or forgot about.
|
| Call it the Chesterton's Fence of 'which'.
| godelski wrote:
| > I just prefix it with a backslash: \grep
|
| I have an almost identical grep alias.
|
| Word of warning, I use `\grep` quite frequently. The usage is
| when you are piping after grep or saving to a variable.
|
| Illustrative example: $ TO_DL=$(curl
| "https://foo.com/releases/" \ | grep -e
| "latest" \ | head -n1 \ ) $ curl
| $TO_DL curl: (3) bad range in URL position XX
| https://foo.com/releases/latest.tar.gz
| ^^^^^^
|
| Annoyingly `--color=auto` can change the representation of the
| characters so when you run again there's a mismatch. I just
| find `\grep` easier than `grep --color=never`.
|
| Annoying footgun, but something to be aware of in case you go
| down this extremely confusing rabbit hole like me. I couldn't
| figure it out until I decided to hexdump the string.
|
| [Side note]: My first thought reading the article was also
| about how `\\` basically solves the problem but they do have
| one advantage in that they can do `,<tab>` and get a list of
| all their custom commands. Personally not worth it for me but I
| can definitely see this being useful for some. Especially on
| shared systems. But getting everyone to prefix a script name
| seems just as unlikely as getting everyone to place programs in
| the right location.
| karolist wrote:
| Interesting, though I never had enough custom scripts to justify
| this, I prefer oh-my-zsh plugin style short aliases instead, i.e.
| https://github.com/ohmyzsh/ohmyzsh/tree/master/plugins/git
| 1vuio0pswjnm7 wrote:
| I use a different prefix character, e.g. "[", but I have been
| doing this for years
|
| 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
| feelamee wrote:
| do you publish dotfiles and scripts anywhere? I'm interested to
| see them
| mathfailure wrote:
| > I prefer giving scripts numbers instead of names
|
| > Something like "[number"
|
| > It contains 100s of short scripts
|
| So you call scripts like [1 [2 [3 [4 ... and remember what each
| one of them does? If yes - that's nuts, I'd visit a doctor.
| 1vuio0pswjnm7 wrote:
| "..., I'd visit a doctor"
|
| But I'm not you
| renewiltord wrote:
| This is utterly unhinged. I freaking love it. It reminds me of
| the old joke about prisoners and numbers for jokes (Stanislaw
| Lem has a similar concept in a book):
|
| _A prisoner, new to a particular cell block, was surprised to
| discover that his fellow inmates passed much of their day by
| calling out numbers, after which they would laugh heartily for
| a few moments. Every few minutes an inmate would call out a
| number and everyone would laugh, and then, after a few moments
| of silence, someone else would call out a number, and once
| again laughter. The inmate asked one of the other inmates whom
| he 'd come to know to explain this strange behavior to him.
|
| "It's simple", came the reply. "We know all of our jokes by
| heart, and there's really no reason to tell them at lenght.
| Instead, we simply call them out by number."
|
| Though this was strange to him, the new inmate thought he'd
| join in on the fun. After a few weeks listening to the jokes,
| he took some initiative and called out "number 27!". But nobody
| laughed. This seemed very strange to him, since he'd heard
| others call out that same number, with everyone laughing
| afterwards. After waiting and waiting, with still no laughter,
| he finally asked: "why is it that when others call out that
| joke you laugh, and when I called it, nobody laughed?".
|
| The reply promptly came: "You told it wrong"._
| 1vuio0pswjnm7 wrote:
| I have zero problems with the terseness of the k language, the
| names of the source files nor the source code they contain
|
| I find brevity easier to work with. I wish all software was
| like that
|
| I like the shell (ash not bash). I like assembly language
|
| I have to "adjust" to verbosity, and sometimes I honestly
| can't, it's paralyzing to the brain, terseness feels more
| natural
|
| Why not name scripts in natural language like an LLM prompt
| perhaps (I don't use LLMs so pardon the ignorance), with spaces
| and punctuation
|
| Bash allows it echo echo hello > "dear
| computer, please output the word \"hello\". thank you"
| chmod +x "dear computer, please output the word \"hello\".
| thank you" "dear computer, please output the word
| \"hello\". thank you"
|
| That might make sense if I was using the scripts to communicate
| with a another person, or if I intended other persons besides
| me to use the scripts
|
| But neither of those things is true. The scripts are for
| communicating with a computer and are intended to be used only
| by me
|
| UNIX allows anyone to rename any file to whatever they want.
| The UNIX user is free to pursue their own preferences in
| naming, whatever those may be
| ndsipa_pomu wrote:
| I appreciate the idea, but the comma just looks horrible to me as
| part of a filename. I can imagine someone unfamiliar with the
| naming scheme to get confused.
|
| 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)
| eterps wrote:
| I use my_ as a prefix.
| JamesTRexx wrote:
| Whenever I see "my" as a prefix, it feels like such a
| childish "my first Sony" thing. I hate official sites using
| that.
| SoftTalker wrote:
| This was actually the same feeling I had when I tried to
| learn perl. I just had a visceral dislike for "my" as the
| keyword to declare a local variable.
| ndsipa_pomu wrote:
| I used to use "do" as a prefix e.g. "doBackup"
|
| 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.
| k3vinw wrote:
| That's a more meaningful prefix than "," at the expense of a
| couple more key strokes. I consider that to still be a win in
| the book of tab completions.
|
| I would replace underscore with "-" or "."
| ndsipa_pomu wrote:
| I'd warn against creating files starting with "-" as that
| can lead to unexpected results with tools if you forget to
| use "--" to end options. Nothing wrong with using "my-" as
| a prefix though.
| layer8 wrote:
| Underscore requires pressing Shift, however.
|
| > 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? ;)
| ndsipa_pomu wrote:
| Well dotfiles demonstrate that punctuation can have a special
| meaning in filenames.
|
| 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.
| layer8 wrote:
| For me it's not about quickness, but about strain. Like in
| RSI.
| necovek wrote:
| On non-English keyboards (Serbian/Croatian/Slovenian, but as
| they are based on QWERTZ, I imagine German and possibly
| others too), both "+" and "-" might not require pressing
| Shift either, and are much better characters than comma.
| layer8 wrote:
| These are inconvenient for doing anything with the script
| files except invoking them, because these characters
| introduce command-line options.
| necovek wrote:
| Which was the point here, wasn't it? Script files that
| you will be commonly running and only editing rarely, I'd
| optimize for how easy they are to run, not operate other
| commands on them from within a shell.
| gugod wrote:
| I tried a variant or this idea so many years ago after I leaned
| git and rearranged some of my personal tools as subcommands (like
| git) of a single executable named "dude,"
|
| It went weird pretty quickly...
| eMPee584 wrote:
| .. examples?
| renewiltord wrote:
| dude, whois my.car
| caeruleus wrote:
| Prefixing commands solves the namespace problem and
| discoverability (at least partly). I use a slightly more
| sophisticated method, which helps me remember which custom
| utilities are available and how to use them: sd [1], a light
| wrapper written for zsh that, in addition to namespaces, provides
| autocompletion, custom help texts + some other QoL enhancements.
| Can definitely recommend if you're looking for something a bit
| more fancy.
|
| [1] https://github.com/ianthehenry/sd
| ljouhet wrote:
| Most of my aliases contain `--` for the same reason, `git--
| progress`, `grep--rIn`, `nvidia--kill`, `ollama--restart`, `rsync
| --cp`, `pdf--nup`...
|
| Easy autocomplete, I know there won't be any collision, and which
| command is mine.
| finghin wrote:
| Great hack!
| mathfailure wrote:
| Kinda makes no sense to me: so you don't use '--' as a prefix,
| you use it in the middle of an alias, so you first have to
| autocomplete, say, 'gi' not to 'git' but to 'git--progress'.
| What does that alias do? Doesn't it call git with some args? If
| so - why not just alias it to git?
| jph wrote:
| Clever hack! <3 I also do namespacing yet in a different way.
|
| 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.
| mromanuk wrote:
| It's clever, but is not aesthetic. A comma feels unnatural in the
| fs.
| mystifyingpoi wrote:
| It doesn't have to be a literal file, it can be an alias.
| lupire wrote:
| That doesn't make it "feel" less "unnatural".
| layer8 wrote:
| So did the dot in dotfiles originally. You'll get used to it if
| you want to.
| tomcam wrote:
| 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.
| pm215 wrote:
| It's not a completely non special character: for instance in
| bash it's special inside braces in the syntax where
| "/{,usr/}bin" expands to "/bin /usr/bin". But the need to start
| that syntax with the open brace will remind you about the need
| to escape a literal comma there if you ever want one.
| mike-the-mikado wrote:
| Until someone forces you to use a file system that cannot
| tolerate commas...
| layer8 wrote:
| Which file system would that be?
| icedchai wrote:
| Many early file systems like the original FAT, RSX-11, VMS
| ODS-2 ... Probably not a concern for anything in the past
| 30 years.
| XCSme wrote:
| What about using the filename in arrays in bash/sh?
| layer8 wrote:
| But Bash arrays don't use comma, what's the problem?
| pmarreck wrote:
| Have you met Bash? It's a shrine to space-delimited
| everything lol
| layer8 wrote:
| I reworded my comment for clarity now.
| XCSme wrote:
| Oh, that might be true, I do remember encountering some
| escaping issues when creating a more complex POSIX (or
| bash) script that involved lists and iterating through
| stuff.
|
| 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,,,.txt
| XCSme wrote:
| Imagine seeing this code: echo
| file{",",",,",",,,"}.txt
| mathfailure wrote:
| Ah, I see you're a man of culture as well!
| layer8 wrote:
| You never used CVS/RCS with its ",v" files?
| xyzzy_plugh wrote:
| You may enjoy learning about the [ binary.
| impoppy wrote:
| Why so many people use ~/bin/? What's wrong with ~/.local/bin?
| zhouzhao wrote:
| Nothing. I also use `~/.local/bin/`
| dark-star wrote:
| ~/bin/ preceeds the XDG Base Directory Specification.
|
| ~/.local was only invented around 2003 and gained widespread
| usage maybe 15 years or so ago...
|
| People used ~/bin already in the 90s ;-)
| 1313ed01 wrote:
| Random things are installed in ~/.local/bin. In ~/bin I have
| only what I put there.
| mixmastamyk wrote:
| Python and rust (for example) package managers install user
| wide tools there.
| pmarreck wrote:
| The latter is XDG.
|
| ~/bin predates it.
|
| And of course you can use both.
| kps wrote:
| Personally I use ~/opt/ _/ bin where ~/opt is a 'one stop shop'
| containing various things, including a symlink to ~/local and
| directories or symlinks for things that don't play well with
| others (e.g. cargo, go), and an ~/opt/prefer/bin that goes at
| the start of PATH containing symlinks to resolve naming
| conflicts.
|
| (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.
| lupire wrote:
| What's the difference between opt and local?
|
| I thought was for mixin externally provided systems like
| Homebrew, local is for machine or org-level customizations,
| and ~ is for user-level customizations.
| kps wrote:
| /opt showed up as a place for packaged software, where each
| package (directory) has its own bin/, lib/, man/, and so
| on, to keep it self-contained rather than installing its
| files in the main hierarchy. ~/opt is just a per-user
| equivalent, analogous to /usr/local vs ~/.local.
|
| The advantage of /opt is that multi-file software stays
| together. The disadvantage is that PATHs get long.
| xorcist wrote:
| Why would you want to store your binaries in a hidden
| directory?
|
| It kind of goes against the idea why dotfiles are dot-prefixed.
| maleldil wrote:
| I use ~/.local/bin for installed programs, and ~/bin for my own
| scripts.
| gucci-on-fleek wrote:
| I personally use both, each for different purposes.
|
| I 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.
| mathfailure wrote:
| People tend to want some separation between what's theirs and
| what's others. Other programs/scripts quite often put something
| into ~/.local/bin, so it's not yours actually, it's theirs.
| aniou wrote:
| I prefer ~/bin/ for my scripts, links to specific commands,
| etc.
|
| ~/.local/bin is tedious to write, when I want to see directory
| content and - most important - I treat whole ~/.local/ as
| managed automatically by other services and volatile.
| laughing_snyder wrote:
| > Like many Unix users, I long ago created a ~/bin/ directory in
| my home directory
|
| `.local/bin` seems to be much more common in my experience for
| this use case. And for good reason.
| zhouzhao wrote:
| Unclutter your $HOME!
| Levitating wrote:
| ~/bin is actually created per default on OpenSUSE (though it's
| removal has been discussed several times).
| yunohn wrote:
| I read this blog a few years ago, and implemented it soon after
| with a refresh of my rc files and shortcuts. Gamechanger - has
| helped me every single day since. It's easy to remember,
| autocompletes easily, and adds a little flair of personalization.
| tezza wrote:
| This is a really good practical step if you worry about name
| collisions
|
| quick, easy and consistent. entirely voluntary.
|
| Bravo
| vitorsr wrote:
| Nice although I think the ASCII comma _feels_ wrong as part of a
| filename even if for purely aesthetic reasons.
|
| 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.
| diydsp wrote:
| Its some what natural to german spkrs who use a special set of
| double quotes to start a quote in print.
| skerit wrote:
| I would have never thought of that. Funny that a comma can be
| used like that.
|
| Off-topic: What the hell is that font on this website? And why
| does the "a" look like that?
| groue wrote:
| Gentium is a very beautiful font:
| https://software.sil.org/gentium/
| feelamee wrote:
| can someone explain security consideration of placing scripts
| into $HOME? Some time ago I moved all my scripts to
| /usr/local/bin, because I feel that this is better from security
| perspective.
| Galanwe wrote:
| There are no security implications, on the contrary.
|
| 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.
| layer8 wrote:
| Someone with access to your home dir can also set your $PATH
| and aliases to anything they want, so I don't see any extra
| security considerations here.
| alzee wrote:
| Using commas in filenames feels kind of weird to me, but I do use
| a comma as the initiator for my Bash key sequences. For example:
| ,, expands to $ ,h expands to --help ,v expands to --version ,s
| prefixes sudo
|
| You put keyseqs in ~/.inputc, set a keyseq-timeout, and it just
| works.
| pmarreck wrote:
| would an alias just work in this use-case?
| listeria wrote:
| Global aliases are a zsh feature and not avaliable in bash.
| So if you want: openssl ,v
|
| to expand to... openssl --version
|
| readline seems like the way to go.
|
| Then again most of the examples OP gave are usually available
| as short options, and aliasing ,s to sudo is certainly
| possible. So the only one which makes sense to me is ,,=$.
| But it's probably not worth the trouble to my muscle memory.
| pmarreck wrote:
| also. did you mean .inputrc ?
| zahlman wrote:
| You could also do this sort of thing with XCompose, yes?
| Tade0 wrote:
| As a non-native English speaker I just name them in my native
| language or using British English spelling.
|
| 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.
| temporallobe wrote:
| I don't think this is a terrible idea, though stylistically it
| bothers me. I suppose you could simply have a prefix command
| router that would essentially do the same thing. I also started
| using "task" recently and it's been a game changer for my CLI
| life.
| mogoh wrote:
| What is task?
| alex-moon wrote:
| It is like make but designed specifically for the way
| non-C(++) users - people like me for example adding scripts
| like "make run" and "make build" to my node/python/PHP/etc
| repos - use it. It is great! I still don't use it literally
| just because make is already installed on any *nix system I
| encounter day to day.
| renewiltord wrote:
| I used task previously and now use mise for it since I have
| a mise version file usually anyway.
| temporallobe wrote:
| Interesting, I have never compared make with task but I
| suppose there's some overlap. My favorite feature is that
| it's cross-platform. I do use it for performing complex
| builds (like chaining several environment setup and docker
| compose commands, etc.). Of course you could do this with
| shell scripts, but this adds a layer of abstraction.
| nickelpro wrote:
| Properly manage PATH for the context you're in and this is a non-
| issue. This is the solution used by most programming environments
| these days, you don't carry around the entire npm or PyPI
| ecosystem all the time, only when you activate it.
|
| 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.
| dcchuck wrote:
| I prefer all my custom commands as 1 letter.
|
| 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
| dddw wrote:
| d for deploy to production
| Ylpertnodi wrote:
| f for friday
| maleldil wrote:
| r for uv run
|
| j for just
|
| I use fish abbreviations for this, as they expand to the full
| command in the shell history.
| jkercher wrote:
| Tangentially related. Don't ever put "." in your PATH. I used to
| do this to avoid typing the "./" to execute something in my
| current directory. BAD IDEA. It can turn a typo into a fork bomb.
| I took down a production server trying to save typing two
| characters.
| Kiboneu wrote:
| lol. What a beautiful footgun -- for such a tiny optimization.
| lanyard-textile wrote:
| Elaborate?? "." has been at the end of my PATH for like 20
| years.
| ahepp wrote:
| Just to save the trouble of writing './'?
| zelphirkalt wrote:
| Why does this go wrong and in what situation?
| Kiboneu wrote:
| A trip down the recursion hole. Also, scripts will inherit
| the relative path so they will have different absolute paths
| from each other. Seems easier to just type ./ so it's kinda
| funny in a "UNIX haters handbook" kind of way, but it's not
| even a fault in linux's command interface in that case. We've
| all been there.
|
| Oh, that's without even going into the security risks and
| loss of portability.
| renewiltord wrote:
| Presumably a script that aliases a common thing or something
| and then it uses the same. E.g. someone adds ./sed that has
| some default params and calls sed. You're intended to call it
| with ~/not-in-path/defaulted/sed and it is supposed to then
| call sed but instead calls itself if it's earlier in the path
| hierarchy.
|
| Might even be as simple as "detect if I'm running gnu sed or
| bsd sed and use the appropriate one". Obviously you can not
| have this problem by being smart about other things but
| defense in depth right?
| mathfailure wrote:
| Not if if you APPEND the dot path to the PATH env: the
| system traverses the dirs specified in the PATH env from
| left to right and stops at first match. Your system's sed
| binary is in the dir that's to the left of your '.' dir.
| necovek wrote:
| Somebody mentioned it elsewhere, but it is a security risk:
| if you end up in a directory that's not under your control,
| and you do a "ls", it might execute "./ls" instead of
| /usr/bin/ls, and that can be doing anything, including piping
| your ~/.ssh/id_* to a remote server.
|
| This can also happen by downloading something off the
| internet (git clone, or tar xz foo.tar.gz), or on a multi-
| user system (eg. someone can put any of these common commands
| into /tmp/ and wait for you to drop into it and try a "ls"
| there) -- if you have any untrusted content anywhere, you are
| exposed.
| mathfailure wrote:
| > if you end up in a directory that's not under your
| control, and you do a "ls", it might execute "./ls" instead
| of /usr/bin/ls,
|
| Not if if you APPEND the dot path to the PATH env: the
| system traverses the dirs specified in the PATH env from
| left to right and stops at first match. Your system's ls
| binary is in the dir that's to the left of your '.' dir.
| mathfailure wrote:
| I like to follow my own convention where I name files with
| shell scripts with an extension: .sh for POSIX-compatible
| scripts, .bash for scripts with bashisms or .zsh for scripts
| with zshisms.
|
| If I ever wanted to achieve what you initially wanted to
| achieve - I could use something like
|
| alias -s sh=sh
|
| alias -s bash=bash
|
| alias -s zsh=zsh
|
| Just like I do bind .txt and .conf to 'less', .pdf to 'qpdf',
| .json to 'ijq', video formats to 'mpv' and so on.
| zahlman wrote:
| Might I ask exactly what the typo was?
| marcosdumay wrote:
| It used to be very common to "own" a unix system by adding a
| `ls` binary in some folder and waiting for an administrator to
| run it.
| bobbylarrybobby wrote:
| Why would this own a server? ls lists itself, but listing
| itself shouldn't cause it to run again? Where's the infinite
| loop that brings the server down?
| suprjami wrote:
| I think parent comment means "cp badthing ls" and leave it
| latent for someone to run. Maybe $PATH has CWD first for
| convenience?
| Dove wrote:
| In many contexts in which I am trying to deconflict namespaces, I
| use my initials. I hadn't thought about it in this particular
| context, though now that I do, it seems fortunate that I am ced
| rather than sed.
| michaelcampbell wrote:
| Glad it worked for OP, but I've never once in 30+ years of this
| had a conflict that did something I didn't want. ~/bin/ is early
| in my PATH, and for a good reason. Things I put in there I want
| to take precedence, so I use this to purposely override provided
| bins. (Though I can only think of one time I wanted to do that,
| too.)
| macintux wrote:
| This has been a popular topic nearly every time the post makes
| the HN front page.
|
| * 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)
| elhosots wrote:
| I think its a fairly good idea - but for myself, i had already
| mapped csh's default history character (!) to a comma (,) for the
| same reason - no shift key to invoke.
| mixmastamyk wrote:
| csh? I used the enhanced tcsh on Irix in the 90s.
| matheus-rr wrote:
| This is one of those "obvious in hindsight" tricks. The comma
| prefix gives you a namespace that's guaranteed to never collide
| with system binaries, shell builtins, or anything from a package
| manager.
|
| 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.
| pkulak wrote:
| There's this program on nix that lets you type a comma, then any
| application name that exists anywhere in the Nix repos. It then
| downloads that app and runs it once, without "installing" it.
| Sometimes I find myself running something dozens of times this
| way before I realize it should probably be in my config.
| xyzzy_plugh wrote:
| https://github.com/nix-community/comma
| Arcuru wrote:
| I'm not sure I'll ever understand why they replaced their
| working ~50 line shell script with a Rust program that just
| shells out to the same nix-* commands. I appreciate that
| there are some safety benefits, but that program is just not
| complex enough to benefit.
| rafram wrote:
| Because it's "a proper language" [1]. Not to mention
| webscale!
|
| It does seem to do some more complex stuff now that
| would've been annoying, but not impossible, to write as a
| shell script.
|
| [1]: https://github.com/nix-community/comma/pull/19
| aidenn0 wrote:
| Shell is already memory safe, so there's not even "we
| replaced C" to lean on.
| synergy20 wrote:
| instead of using ~/bin I use ~/installed/bin, sometimes I need
| build a command from source then install it, which might have
| share/ man/ etc so I can avoid installing them under the home
| dir.
| mixmastamyk wrote:
| ~/.local/ could work for this, and as another user mentioned
| easier to separate the back up.
| nh2 wrote:
| Worth pointing out that with Nix/NixOS this problem doesn't
| exist.
|
| The problem in other distros is that if you prefix PATH so that
| it contains your executable "foo", and then run a program that
| invokes "foo" from PATH and expects it to do something else, the
| program breaks.
|
| With Nix, this problem does not exist because all installed
| programs invoke all other programs not via PATH but via full
| absolute paths starting with /nix/store/HASH...
| ablob wrote:
| So if I want to use grep in a small script, do I have to write:
|
| /nix/store/grep-hash -flags files | /nix/store/head-hash
|
| instead of: "grep -flags files | head"?
| xaduha wrote:
| [user@nixos:~]$ which grep /run/current-
| system/sw/bin/grep [user@nixos:~]$ ls -l
| /run/current-system/sw/bin/grep lrwxrwxrwx 1 root
| root 65 Jan 1 1970 /run/current-system/sw/bin/grep -> /nix/
| store/737jwbhw8ji13x9s88z3wpp8pxaqla92-gnugrep-3.12/bin/grep
|
| Basically, it is still in your environment, so I don't see
| how he can claim that this problem doesn't exist in Nix,
| unless you use flakes like a proper Nix afficionado.
| aidenn0 wrote:
| Yes, the original comment that this problem doesn't exist
| in Nix is wrong for a typical user environment.
|
| It does contain the issue a bit though:
|
| I'm running isync in a systemd service, yet the program
| "mbsync" is not in my path. I have several services
| installed, yet their programs aren't in my path. My e-mail
| client shells out to "file" for mime-type verification, yet
| "file" is not in my path.
|
| Run "compgen -c |wc -l" to get a list of commands; its over
| 7000 on my Ubuntu system and right around 2000 on my NixOS
| system.
|
| As an aside, the packages that put the most executables in
| my path are probably going to be in the path for most NixOS
| installs (231 just for coreutils+util-linux):
| 27 /nix/store/csxa6mi2mpjl9vqxbv2j0bha6sz6nbjw-cups-2.4.14
| 31 /nix/store/334afxah19b3hr6ll93pfxlcyhhh2vws-
| pipewire-1.4.9 31
| /nix/store/h2jsb5i4yfblr2f3ac2c7zpmlmj7zjym-perl-5.40.0
| 33
| /nix/store/914x32c982bs3i1998yxvkg9svm3ycr5-shadow-4.18.0
| 33 /nix/store/a6s3hzj3b2z6rsyfkjyxwn265iyfl2gn-
| mtools-4.0.49 33
| /nix/store/jky7jszaci5n7g426wf6nsg5dmik9nfw-kbd-2.9.0
| 37 /nix/store/2v1l6mqz0d7mfpp4ksw2048v3g0a1a19-hplip-3.25.2
| 45
| /nix/store/90wlc37ljr6rpy2lan46bp0gq19vbgl5-iptables-1.8.11
| 48 /nix/store/1byhxs7b28grh8s15jc2dvs2zg36swjb-
| lvm2-2.03.35-bin 61
| /nix/store/9xwxjkrwxjsvc5gs1l0syr4wbfvvvvcn-bluez-5.84
| 64
| /nix/store/zf8qy81dsw1vqwgh9p9n2h40s1k0g2l1-systemd-258.2
| 72 /nix/store/1igrj9w84w7s3r80l3nkxcqwd84sw9mz-qemu-10.1.2
| 106 /nix/store/v4q3154vdc83fxsal9syg9yppshdljyk-coreutils-
| full-9.8 125
| /nix/store/3c6r8gh8zrqw8xmncmlj9vivz9rz6r30-util-
| linux-2.41.2-bin
| xaduha wrote:
| True enough, but in my experience it's not really much of
| a problem because if I'm not doing Nix, then I'm doing
| containers which are widely available.
|
| What can be a problem is muscle memory, when you expect
| it to autocomplete one way and it doesn't because
| something you want now shares first two or three letters
| with something else in your path. That's where FIGNORE
| comes in.
| aidenn0 wrote:
| If it's a one off, you just use something like "nix shell" to
| add it to your path for running the script.
|
| For non one-off sorts of things, you would substitute in the
| nix expression "${gnugrep}/bin/grep" the "${gnugrep}" will
| expand to "/nix/store/grep-hash" and also make a dependency
| on the gnugrep package, so that the grep install won't get
| garbage-collected as long as your package is still around.
|
| Here's an example[1] from a package expression for e-mail
| client I use, which will shell out to base64 and file.
| Upstream relies on these two programs being in $PATH, but
| this replaces the string used for shelling out with the
| absolute path in the nix store.
|
| For shell scripts, I'll just do something like this near the
| top: GREP="${GNU_GREP:-$(command -v grep)}"
|
| Then I use "$GREP" in the script itself, and develop with
| grep in my path, but it's trivial to prepend all of my
| dependencies when I bundle it up for nix.
|
| 1: https://github.com/NixOS/nixpkgs/blob/master/pkgs/by-
| name/no...
| ahepp wrote:
| The "solution" of only ever using full absolute paths works on
| any unix system, doesn't it?
| aidenn0 wrote:
| Yes with a but:
|
| NixOS simultaneously smooths the path to using absolute paths
| while putting some (admittedly minor) speed-bumps in the way
| when avoiding them. If you package something up that uses
| relative paths it will probably break for someone else
| relatively quickly.
|
| What that means is that you end up with a system in which
| absolute paths are used almost everywhere.
|
| This is why the killer feature of NixOS isn't that you _can_
| configure things from a central place; RedHat had a tool to
| do that at least 25 years ago; it 's that since most of /etc/
| is read-only, you _must_ configure _everything_ from a
| central place, which has two important effects:
|
| 1. The tool for configuring things in a central place can be
| much simplified since it doesn't have to worry about people
| changing things out from under it
|
| 2. Any time someone runs into something that is painful with
| the tool for configuring things in a central place, they have
| to improve the tool (or abandon NixOS).
| polyrand wrote:
| I do this, and it's a huge quality of life improvement. No so
| much because of shadowing existing binaries, but for better
| command auto-complete. For example: I have a bunch of tmux
| utilities and all start with `,t` which is not a polluted
| command-name prefix compared to just `t`.
|
| But I'm now facing the problem that LLM agents don't like this,
| and when I instruct them to run certain tools, they remove the
| leading comma. It's normally fixed with one extra sentence in the
| prompt, but still inconvenient.
| ahepp wrote:
| One could set an env var to their local bin dir which is
| otherwise not in the path, like L=/home/ahepp/.local/bin, and
| then do $L/mycommand. Doesn't meet the OP's requirement of no
| shift key.
|
| Or prefix files in the local bin dir with a couple letters from
| your username, like /home/ahepp/.local/bin/ah-mycommand
| moritzwarhier wrote:
| Why not just start every alias or script with e or something?
| ezfe wrote:
| Comma is easier to type and less visually distracting
| moritzwarhier wrote:
| makes sense, article mentions not wanting composite keys.
| There goes my sarcasm.
|
| However, I'd advocate for an e key then.
| tasuki wrote:
| I never did this and never once experienced a name conflict.
| grimgrin wrote:
| in vim i am very fond of two mapping prefixes: <space> and ,
|
| they're both so easy to reach for
| bilbo-b-baggins wrote:
| Love this thread reminding me that most experts in computers are
| unhinged lunatics doing convoluted and tortured things on a daily
| basis that they consider perfectly normal and even convenient.
| jmux wrote:
| yes this is totally cursed but I kinda love the idea
___________________________________________________________________
(page generated 2026-02-07 23:00 UTC)