← Back to context

Comment by chasil

7 hours ago

I think the appropriate method by POSIX rules would be:

  export PATH="$PATH:"~/.local/bin

I may be wrong. If I'm not, that works in any POSIX-compliant shell.

Edit: this appears to work properly with mksh on my phone:

  :/ $ export PATH="$PATH:"~/.local/bin
  :/ $ print $PATH
  /product/bin:/apex/com.android.runtime/bin:/apex/com.android.art/bin:/system_ext/bin:/system/bin:/system/xbin:/odm/bin:/vendor/bin:/vendor/xbin:~/.local/bin

That's a literal ~ in your path, the exact problem the blog post talks about.

Your use doesn't count as a "word", per man bash. Tilde is only expanded to home at the start of a typically whitespace-separated word, and your tilde is in the middle of one.

> If a word begins with an unquoted tilde character (‘~’), all of the characters up to the first unquoted slash (…) are considered a tilde-prefix. (…)

> word A sequence of characters considered as a single unit by the shell. Also known as a token.

  • My initial syntax does work in dash (and bash), but all these shells appear to rely on expanding ~ inside a word, that your source asserts is not POSIX (which I do not contest).

    Perhaps a succinct and compliant expression could be:

      export PATH="$PATH:$(printf %s ~/.local/bin)"
    

    That comes at the cost of forking a subsell.

    Edit: 2.6.1 Tilde Expansion in the POSIX standard says that ~ may be expanded "following any unquoted <colon>".

    https://pubs.opengroup.org/onlinepubs/9699919799/utilities/V...

    That being so, the most succinct and compliant version is my first variant, with the colon moved outside the quotes:

      export PATH="$PATH":~/.local/bin
    

    Thank you for prompting me to look this up.