12

I have a script that begin like this

#!/bin/bash
VALKYRIE=~/myProjects/valkyrie
source $VALKYRIE/cluster.conf

but when I run it it returns line 2: ~/myProjects/valkyrie/cluster.conf: No such file or directory

but the file exist and when I run source ~/myProjects/valkyrie/cluster.conf it runs fine. Any idea? I set VALKYRIE variable elsewhere so hard-code in the path isn't an option.

Khoi
  • 223
  • 1
  • 2
  • 5
  • I'm not 100% sure if this will help, but you could try fully quoting the variable, in case there are spaces in ~. Hence, `source "${VALKYRIE}/cluster.conf"`. – Sparhawk Jun 01 '13 at 03:41
  • no, it doesn't help. – Khoi Jun 01 '13 at 03:47
  • Are you saying that running `source ~/myProjects/valkyrie/cluster.conf` works, when you replace the last two lines of the script? (Or from the command line?) – Sparhawk Jun 01 '13 at 03:52
  • it works whether from command line or in the script – Khoi Jun 01 '13 at 03:54
  • 1
    I think it's something to do with `~` not expanding properly. When I run your script with an intentionally fake path, the error doesn't say `~`, but expands the path. Can you try replacing the `~` in your script with the absolute path? Also, try running the following in a script `echo ~`. – Sparhawk Jun 01 '13 at 04:04
  • you're right, not using `~` did the trick. Thanks a lot! – Khoi Jun 01 '13 at 04:10
  • Is that good enough? Should I write it up as an answer, or do you want to use `~` and work out why it doesn't work? – Sparhawk Jun 01 '13 at 04:12
  • 2
    You could also try `$HOME` instead of `~`. – Sparhawk Jun 01 '13 at 04:16
  • The code you show doesn't match the error message. You must have written `VALKYRIE="~/myProjects/valkyrie"` -- quotes would suppress the expansion of the tilde. – glenn jackman Jun 01 '13 at 04:40
  • to be exact I used `VALKYRIE=~/myProjects/valkyrie` without quotes inside `~/.pam_environment` – Khoi Jun 01 '13 at 07:15
  • 4
    @Khoi That explains it. `~/.pam_environment` is not a shell script, so it doesn't do the common things you'd expect from a shell, such as tilde expansion and parameter expansion, so neither `~` nor `$HOME` will be replaced. If you move that line to `~/.profile` instead, and add `export ` in front, it should work. – geirha Jun 01 '13 at 08:41
  • It's said that the recommended way to add environment variable is through `~/.pam_environment`. Well I don't need to use `~` nor `$HOME`, works for me. – Khoi Jun 01 '13 at 09:24

1 Answers1

10

~ doesn't appear to be expanding properly. When I run your script with an intentionally fake path, the error doesn't say ~, but expands the path (i.e. /home/sparhawk/fakepath not ~/fakepath. You could try using $HOME instead of ~, or using the full path in the script instead.

(I'm not sure why ~ doesn't work on your system, as your script works fine for me.)

Sparhawk
  • 6,872
  • 7
  • 48
  • 78
  • When you look at the order that bash performs expansions (http://www.gnu.org/software/bash/manual/bashref.html#Shell-Expansions), you'll see that tilde expansion happens *before* variable expansion. That's why `$HOME` is better than `~` in a variable – glenn jackman Jun 01 '13 at 04:29
  • @glennjackman I'm not sure I understand. Why would priority matter for variables vs. `~`? – Sparhawk Jun 01 '13 at 04:33
  • 1
    it's not exactly "priority", it's simply what comes first. Consider `x="~/.bashrc"; ls $x` -- in the order of expansions for the "ls" command, bash looks for a tilde and doesn't find one; eventually bash sees a variable and expands it. bash does not go back and look for tildes again, at this point it's just a plain character. and there are no files in the current directory that begin with a tilde. – glenn jackman Jun 01 '13 at 04:41
  • Ah okay. I think I get it. I've always wondered why that command fails and `x=~/".bashrc"; ls $x` works. Thanks for the info. – Sparhawk Jun 01 '13 at 04:43
  • My path was within the quotes so I had to remove the quotes and it worked. – nick-s Oct 05 '22 at 02:56