3

On my system*

cd                                                 # move to home
mkdir tempdir
PATH="$PATH:~/tempdir"                             # put tempdir in path
touch tempdir/tempscript
echo -e '#!/bin/bash\necho h' > tempdir/tempscript # write script
chmod u+x tempdir/tempscript                       # make executable
tempscript                                         # execute

will find the script tempdir/tempscript and print h.

However, if we echo $PATH, we will see ~/tempdir at the end of it, so it was not expanded. Which is what we expect to happen, since we put double quotes around the assignment.

I can't find any documentation however on why tilde expansion occurs when evaluating $PATH. (Note that the PATH variable still has the ~ in it.)

Is this portable behavior?

* Mac OS X w/ GNU bash 3.2

Chris Middleton
  • 5,654
  • 5
  • 31
  • 68
  • 3
    In `BASH` it is portable behavior. Have a look at: [Tilde Expansion](https://www.gnu.org/software/bash/manual/html_node/Tilde-Expansion.html) – user3439894 Feb 06 '15 at 19:23
  • 2
    @user3439894, that's true **IF NOT QUOTED**. Quoting prevents tilde expansion, even if assigning to a variable. That's explicitly in the docs you linked: "Each variable assignment is checked for *unquoted* tilde-prefixes" – Charles Duffy Feb 06 '15 at 19:29
  • @Charles Duffy, Okay I guess from now on I qualify everything I say! Yes it's portable when done so within the bounds of the rules and hence why I included the link in my first comment as I expect users to RT*M too! – user3439894 Feb 06 '15 at 19:34
  • 1
    @user3439894, ...but the OP explicitly demonstrated a quoted assignment. A reasonable reader could expect "this" to refer to the code given in that demonstration.- – Charles Duffy Feb 06 '15 at 19:34
  • @CharlesDuffy \@user3439894 You are both right in a way. I'll make the quotes part of it more explicit in my question. – Chris Middleton Feb 06 '15 at 19:35
  • BTW, when doing your testing, I'd suggest using a program other than the shell to execute the child program. Executing the program in a tilde-delimited path through `xargs` or a similar tool will have that effect. – Charles Duffy Feb 06 '15 at 19:40
  • 1
    @Charles Duffy, Okay I missed the quotes on the assignment in the OP! :) – user3439894 Feb 06 '15 at 19:44

1 Answers1

4

No, this is not portable. If your operating system's execl call doesn't perform this expansion, programs that aren't bash will fail to find executables within the given directory.

Note that if you didn't quote the expansion, this would be safe:

PATH=$PATH:~/tempdir   # this is safe -- expansion happens before assignment
PATH="$PATH:~/tempdir" # this is not -- readers are required to expand

While it's generally a best practice to quote all shell expansions, this isn't necessary for assignments, which implicitly prevent string-splitting and glob expansion behaviors.

Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
  • I didn't know that about assignments - thanks. Also, I just tried on a centos 6 system and it worked there as well. So perhaps it's undefined, but mostly consistent, behavior. – Chris Middleton Feb 06 '15 at 19:34
  • 2
    @AmadeusDrZaius Have a look at: [Literal tilde in PATH works poorly across programs.](https://github.com/koalaman/shellcheck/wiki/SC2147) – user3439894 Feb 06 '15 at 19:43