Bash script -e not detecting filename in a variable Bash script -e not detecting filename in a variable shell shell

Bash script -e not detecting filename in a variable


That's an interesting one. Substituting $HOME for ~ works as does removing the quotes from the assignment.

If you put a set -x at the top of that script, you'll see that the version with quotes sets filename to ~/... which is what's given to -e. If you remove the quotes, filename is set to the expanded /home/somebody/.... So in the first case, you see:

+ [ -e ~/... ]

and it doesn't like it. In the second case, you see:

+ [ -e /home/somebody/... ]

and it does work.

If you do it without the variable, you see:

+ [ -e /home/somebody/... ]

and, yes, it works.


After a bit of investigation, I've found that it's actually the order in which bash performs its expansions. From the bash man page:

The order of expansions is: brace expansion, tilde expansion, parameter, variable and arithmetic expansion and command substitution (done in a left-to-right fashion), word splitting, and pathname expansion.

That's why it's not working, the variable is substituted after the tilde expansion. In other words, at the point where bash wants to expand ~, there isn't one. It's only after variable expansion does the word get changed into ~/... and there will be no tilde expansion after that.

One thing you could do is to change your if statement to:

if [[ -e $(eval echo $filename) ]]; then

This will evaluate the $filename argument twice. The first time (with eval), there will be no ~ during the tilde expansion phase but $filename will be changed to ~/... during the variable expansion phase.

Then, on the second evaluation (the one being done as part of the if itself), the ~ will be there during the tilde expansion phase.

I've tested that on my .profile file and it seems to work, I suggest you confirm in your particular case.