The tilde in your PATH may not be your HOME

(disconnect3d.pl)

72 points | by arusekk 3 hours ago

12 comments

  • amarshall 1 hour ago
    Or you can just…not quote the tilde. Folks always seem to reflexively quote “strings” in Bash while not realizing that (almost) everything is a string and most strings are not quoted and it would be odd to do it (e.g. no one is doing `"ls" "-a" "foo"`).
    • Cockbrand 27 minutes ago
      I feel like this is common knowledge and should not be worth mentioning. But then it apparently is not common knowledge, as the article proves.

      Have I run into this at some point?

      I certainly have.

      Have I learned to quote better and only where appropriate from it?

      I certainly have.

      Bourne compatible shells take a while to learn and require some experience. This won't change, but alternatives exist, with their own caveats.

    • vips7L 1 hour ago
      Or just stop using bash. It’s a terrible language to write and has tons of footguns.
      • CodesInChaos 46 minutes ago
        Unfortunately half of its badness isn't isn't the shell itself, but the convention of how parameters are passed to processes on Unix systems.
        • formerly_proven 13 minutes ago
          Array of arguments is vastly superior and more secure than every program/runtime inventing a slightly different way of splitting a command string into an array of arguments. No debate. A real problem is the related birth defect in ssh2.
        • akoboldfrying 20 minutes ago
          Well, the only other way I can think of that it could be done is the Windows way, whereby you pass the unparsed command line, spaces and all, as a string to the new process. And while this is arguably the cleaner interface, in practice it has meant even worse quote handling, since how -- or even whether -- double quotes are parsed now depends on the probably undocumented process startup code chosen by the program's compiler vendor.

          Want to quote a command line that may already contain double quotes, in order to pass it as an argument to some other program? No, you don't. It isn't right to want that.

    • cr125rider 1 hour ago
      The trick is to quote explicitly and correctly. “ and ‘ are different.
      • dylan604 1 hour ago
        why would you use smart quotes in a terminal like that?
        • tom_ 1 hour ago
          They probably fell foul of some browser text box auto-correct.
        • airstrike 1 hour ago
          why would anyone use smart quotes ever
          • mpyne 44 minutes ago
            They are typographically the right thing to have been using all along.

            Using ' and " to pretend to be ‘/’ or “/” is on par with the typewriter days where people would use the l key to stand in for 1 also. A justifiable approximation when technology limitations prevented using the real deal, but an approximation all the same.

            • Dylan16807 31 minutes ago
              Except l has a specific meaning that isn't 1, while the entire purpose of ' and " is quoting (and apostrophe).

              The equivalent of l for 1 is doing font-specific pseudo smart quotes with ` and '

    • dylan604 1 hour ago
      Unless you're running a shell command from python. That was the first time I saw a command string broken down into "string" arguments for every thing like that.
      • thwarted 1 hour ago
        In that case, you're not running a "shell command" from python, you're passing arguments to exec. A shell command would be a string interpreted by the shell, and you'd use that for shell syntax things like having the shell do variable interpolation or redirections as part of executing the command.
    • paulddraper 1 hour ago
      People quote both too often and too little.

      GENERAL RULE

      1. Double-quote dollar sign expressions, and nothing else.

        foo
      
        "$bar"/foo
      
        baz:"$(cat example.txt)"
      
        exec cmd "$@"
      
      2. Single-quote words with a special character, and nothing else.

        'Die Hard'
      
        'ke$ha'
      
      ---

      I should point out that the author's example is NOT fixed by different quoting though.

        # original
        export PATH="$PATH:~/.local/bin/"
      
        # without unnecessary quotes
        export PATH="$PATH":~/.local/bin/
      
      Because tilde expansion happens at the beginning of the word.
  • alexpotato 2 minutes ago
    Not necessarily about tildes but about some of the craziness that can happen with bash at large orgs:

    At a past job, I was trying to figure out what part of my basrhc was setting a particular environment variable. I assumed that it must be some kind of default installed in my user profile and/or inheriting from /etc/<something>.

    I realized pretty quickly that my bashrc was importing some other files. Again, the assumption was that this would be one file deep in the import.

    It turned out there were 10+ layers of import starting from an "ur-bashrc" and then layer upon layer of more and more imports to finally get to a user level profile.

    It was so convoluted that I was going nuts until I found this Stack Exchange post: https://unix.stackexchange.com/questions/813/how-to-determin...

    It turns on "tracing" for bash imports so that you can then narrow down on where the env variable is getting set.

  • the__alchemist 39 minutes ago
    I wish Linux distros would ship a "Terminal"/"CLI" program etc that is decoupled from the scripting language. Have a universal Path env var that isn't tied to a specific shell. Lets you execute cd commands, launch python/git/cargo/arbitrary applications etc, and have a good bookmark + autocomplete system. It feels like the conflation of scripting language + CLI application is the root of these complications and subtleties.

    If you are using shell scripting (And prefer Bash etc over Python), you would keep using Bash/Fish/Zsh etc. If you are using the CLI to launch applications that don't have a GUI, navigate directories and perform file system operations, then you would use the plain terminal.

    • Lerc 33 minutes ago
      I always thought that there should be a proc style file system for simlinks to user specific data.

      I'm not sure why this can't be done. Security people will have a million reasons, I guess it's possible one of them might be valid.

    • dicytea 15 minutes ago
      $PATH is not tied to any specific shell. And what you're describing is a shell, so I'm not sure how it's any different from existing solutions.
      • the__alchemist 1 minute ago
        It is - this is why adding something to the Path is tricky on Linux.
    • akoboldfrying 34 minutes ago
      IIUC, you're describing an extremely restricted (some would say underpowered) shell.

      It sounds like you could make it yourself in ~10 lines of Python or bash. I don't see it catching on, though.

  • FeepingCreature 1 hour ago
    Kind of seems like you should have noticed this by your ~/.local/bin PATH not working?
  • dspillett 45 minutes ago
    I was going to say “it always seems to work for me” then I saw “… actually works in Bash and Zsh, because …”.

    Another Bash-ism I need to be careful not to use when trying to be portable.

    It is worth noting that on a lot of systems /bin/sh isn't bash (or zsh) so if you want to rely on Bashisms (or just can't be bothered looking for them) be specific and use “#!/bin/bash” for you hashbang. On Debian and similar it is usually dash for instance.

  • duncangh 1 hour ago
    I should have read the docs before getting ~/ tattooed on my wrist.
  • very_good_man 1 hour ago
    Reminds me of early days of Cursor when it decided it would be a good idea to create a directory named "~" in my repo root!

    That was a scary mistake to unwind!

  • IshKebab 2 hours ago
    Bash footgun #238503.
    • paulddraper 1 hour ago
      That's standard POSIX.

      Tilde expands when at the beginning of an unquoted word.

      Pretty straightforward.

        ~ or ~/ --> $HOME
      
        ~user --> user's home
      
      ---

      Bash has a few extra.

        ~+ --> $PWD
      
        ~- --> $OLDPWD
      
        ~+N or ~-N --> dirs
      • Joel_Mckay 49 minutes ago
        In most use cases, the bash scripts location is more important than $HOME. This is because it is resilient to changes in user in the session, and parent process current working location contexts. =3

        scriptPath=$(/usr/bin/realpath "${BASH_SOURCE[0]}")

        localPath=$(/usr/bin/dirname "$scriptPath" )

        /usr/bin/echo "localPath = '$localPath'"

    • _ZeD_ 1 hour ago
      well.. it's in zsh (and probably any other *sh) too
      • vbernat 1 hour ago
        In Zsh, you can set PATH with path=(~/.local/bin $path). There, it works as shell expansion works.
    • Joel_Mckay 1 hour ago
      There is a workaround =3

      sudo ln -s /usr/bin/bash /usr/bin/footgun

  • gjvc 1 hour ago
    bad example in the article:

      export PATH="$PATH:$HOME/.local/bin/"
    
    better:

      export PATH="$HOME/.local/bin/:$PATH"
    • Backslasher 1 hour ago
      Afaik it's habit to give system paths precedence so a malicious script can't shadow e.g. sudo and steal your password, escalating a local file write into root
      • toast0 1 hour ago
        Otoh, if you don't put your local path first, you can't override system binaries that you want to override.

        Also, if something can write into your path, it can probably write to your shell config and/or the environment variables.

      • paulddraper 1 hour ago
        AFAIK it's habit to allow your scripts to override system ones, so you can customize behavior.

        I've always seen home dir, homebrew, etc prepending to PATH.

  • hnd9q09qk4 1 hour ago
    [flagged]
  • ska1296 29 minutes ago
    [flagged]
  • mr_mitm 1 hour ago
    So many headaches could be avoided if we only allowed `[A-Za-z0-9._-]` in paths. (Arguably, even `-` can be problematic.) Encoding issues, expansion, parameter separation, ... and I never saw a convincing case in favor of supporting anything else.
    • Dylan16807 23 minutes ago
      If you're trying to avoid headaches then definitely don't allow -. At least not as the first character in a segment.

      And allowing any letters from any language is probably worth the hassle.

    • jetbalsa 1 hour ago
      What about people who do not speak English? or even use Latin letters?
      • mr_mitm 1 hour ago
        The language I grew up with does use non latin letters, I can manage. Then again, it's only four of them, so I get your point ... but I can dream, can't I?
      • ThunderSizzle 1 hour ago
        What Latin letter(s) are you referring to?

        The (classical) Latin alphabet can be fully described by the English alphabet.

        • toast0 1 hour ago
          What about people who do not ((speak English?) or (even use Latin letters?))
        • cowboylowrez 1 hour ago
          unicode names spit
    • dylan604 1 hour ago
      I always joked about setting a custom keyboard layout to replace the space char with the underscore char specifically for avoiding spaces in file paths.