from Hacker News

How to add a directory to your PATH

by alexchamberlain on 2/24/25, 7:16 AM with 63 comments

  • by ljm on 2/27/25, 3:03 PM

    The author's last post was about terminal frustrations[0]

    This is easily one of the most annoying ones, especially when shells will have several different locations to read config from depending on how you start the shell, or what a desktop app will do to try and pull the config in (`exec-path-from-shell` in emacs, for example).

    And you can't really, say, put it in both your `.zprofile` and `.zshrc` or `.bash_profile`, `.profile`, and `.bashrc`, because then it'll get executed more than once and you'd need to maintain some kind of state to prevent that.

    [0]https://jvns.ca/blog/2025/02/05/some-terminal-frustrations/

  • by evntdrvn on 2/27/25, 4:09 PM

    I've worked on maintaining internal dev tooling for some small companies for a while now, and it's a real PITA to write a robust installation script for bootstrapping a new laptop running an arbitrary shell on linux or macOS into a working environment. Way more work than it feels like it should be.

    At this point I've pretty much given in and decided that a containerized dev environment is probably the better solution, but on principle it feels so unsatisfying to have to resort to this :(

    (I know someone is going to mention Nix/Guix ;) but that feels like a giant rabbit hole)

  • by t43562 on 2/27/25, 3:38 PM

    FWIW in bash I have 2 functions:

      path_add() {
          export PATH=$PATH:$(string_join ':' $@)
      }
    
      path_prepend() {
          PATH=$(string_join ':' "$@"):$PATH
          export PATH
      }
    
    These can join an arbitrary list of paths to PATH. e.g.

      path_add /usr/bin /usr/local/bin ~/bin
    
    They depend on another one:

      string_join() {
          local join=$1; shift
          local result=$1; shift
          for p in "$@"; do
            result="${result}${join}${p}"
          done
          echo -n "$result"
          set +x
      }
    
    I also have ones for adding and prepending to LD_LIBRARY_PATH
  • by Joker_vD on 2/27/25, 3:51 PM

    As for path duplication, I personally have

        printf '%s\n' "$PATH" | grep --color=auto -E -e '(^|:)'"$( printf '%s\n' "$1" | sed 's/[][\.|$(){}?+*^]/\\&/g' )"'($|:)' > /dev/null 2>&1
        if [ "$?" = 1 ]; then PATH="$1:$PATH" ; export PATH ; fi
    
    in my version of pathadd().
  • by jmholla on 2/28/25, 3:10 AM

    > Configure your shell to continuously save your history instead of only saving the history when the shell exits. (How to do this depends on whether you’re using bash or zsh, the history options in zsh are a bit complicated and I’m not exactly sure what the best way is)

    I attempted this in bash like so:

    ``` PROMPT_COMMAND="history -a; $PROMPT_COMMAND" ```

    But, that meant every shell was sharing the same history. Pressing up would go to the last command run anywhere, not just my current shell.

    Sadly, I wasn't even trying to solve the problem Julia is talking about here. I just wanted to make sure my history was saved when I shutdown. Still haven't found a great solution to that. My attempts as using traps and signals caused weird issues.

  • by duped on 2/27/25, 3:58 PM

    In my (fever) dreams, there's a directory at `/var/share/env` with the rule that regular files are <file name>=<file contents> and all other file types are ignored. The `env` program can slurp all the files to create the default environment before applying whatever customization are in dotfiles for a shell.

    Want to add to path? `echo ':<directory>' >> /var/share/env/PATH` (or `env --add PATH :<directory>`, or something like that).

  • by MisterTea on 2/27/25, 3:35 PM

    All this path stuff would go away if you have a proper vfs where you bind you other bins over /bin allowing $path to simply read "/bin ." and be done with it.
  • by t43562 on 2/27/25, 3:35 PM

    .bashrc gets run every time a shell starts

    I'm not sure I'd stick a path setting in .bashrc - just because it would make it very difficult to ever override that PATH setting elsewhere.

    You might want that but it might also mess up some other program's attempt to set the PATH and then e.g. run a shell command.

    I usually use .bash_profile or .profile more for this sort of thing and then I have to tell my terminal program to run bash as a login shell and that gives me what I mostly expect.

  • by mathfailure on 2/27/25, 10:38 PM

    I love this blog even though I usually get nothing from the articles that I didn't know before. Still read it and still love it.
  • by bandrami on 2/27/25, 3:19 PM

    But not if the shell is running as an inferior process in an emacs buffer, in which case you have to do yet another thing.
  • by fuzzfactor on 2/24/25, 7:29 AM

    Here's a possible idea for an open-source project if someone is qualified.

    Make it as easy as it is in Windows.

  • by unchar1 on 2/27/25, 5:38 PM

    > fish instructions:

    > set PATH $PATH ~/.npm-global/bin

    Fish has some nice utilities for these type of set calls

    set --append PATH ~/.npm-global/bin