0

I am getting a weird error, can't seem to figure out why.

Especially because it works in one place but not in another scenario.

I have his code that checks whether these directories exist - and the HOME dirs with ~ is failing in this code snippet:

if [[ ! -d "$valueToTest" ]]; then
    echo 'Failed>>:'$valueToTest;
fi;

I get output:

Failed>>:~/.workspace/
Failed>>:~/.ssh
Failed>>:~/.workspace/vim/temp
Failed>>:~/.workspace/vim/backup
Failed>>:~/.workspace/vim
Failed>>:~/test

Like I said it happens ONLY with the ~ expansion to represent my HOME directory.

And this is the ONLY place this is happening as I have OTHER code that checks for path with ~ ie my HOME directory with ~ expansion, AND they work fine!

The directories are being read from value part of an associative array - but I can't see why that would be a problem. Also you can see the output has no quotes or such associated with it.

I have tried with and without double-quotes - no luck.

As in:

$valueToTest
${valueToTest}
"${valueToTest}"

Thank you for help.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
mono-dr
  • 217
  • 1
  • 2
  • 9

1 Answers1

0

Tilde expansion does not happen when ~ is quoted in any way. And unlike pathname or filename expansion, ~ also doesn't expand when it's part of a variable.

If $valueToTest is ~/.workspace/, all of these forms would not work:

[[ ! -d "$valueToTest" ]]
[[ ! -d $valueToTest ]]
[ ! -d $valueToTest ]

And is just synonymous to:

test ! -d '~/.workspace/'

But this would work:

test ! -d ~/.workspace/

Or

test ! -d /home/user/.workspace/

So the fix to your code is that, you should assign the expanded path to your variable instead, and not the unexpanded form:

valueToTest=~/.workspace/    ## Correct assignment.
valueToTest=~'/.workspace/'  ## Correct assignment.
valueToTest=~"/.workspace/"  ## Correct assignment.

valueToTest='~/.workspace/'  ## Incorrect assignment.
valueToTest="~/.workspace/"  ## Incorrect assignment.

set -- ~/.workspace/         ## Correct assignment.
valueToTest=$1               ## (simulates bash script.sh ~/.workspace/)

set -- "~/.workspace/"       ## Incorrect assignment.
valueToTest=$1

The Hack

If it's unavoidable that only the unexpanded form is stored, you can use printf %q and eval to expand your string. So far I find good enough and safe:

printf -v temp %q "$valueToTest"
eval "valueToTest=$temp"

Then test $valueToTest the way you do.

Update

In Bash 4.3, printf %q would already quote tilde characters (~) as well. To fix this you can make those characters unquoted again:

printf -v temp %q "$valueToTest"
temp=${temp//\\\~/\~}
eval "valueToTest=$temp"

You can also allow $HOME to expand:

printf -v temp %q "$valueToTest"
temp=${temp//\\\~/\~}
temp=${temp//\\\$HOME/\$HOME}
eval "valueToTest=$temp"

Another possible fix also is to just convert them directly:

valueToTest=${valueToTest//\~/$HOME}
valueToTest=${valueToTest//\$HOME/$HOME}
konsolebox
  • 72,135
  • 12
  • 99
  • 105
  • konsolebox - This did not work for me: printf -v valueTemp %q "$valueToTest"; eval "valueToTest=$valueTemp";; I also tried in assigning from associated array because in another part of my code this works: ls -al ${gA_SysLocalPATH[HOME/.ssh]}. – mono-dr Aug 27 '14 at 14:35
  • It is only when I load these arrays from a file that these tests do not work. However if I assign directly, in the bash code, as in ${gA_SysLocalPATH[HOME/.ssh]}=~/.ssh - that they seem to work. – mono-dr Aug 27 '14 at 14:37
  • konsolebox - In reading from the file I even tried your code before assigning into the array I test from later (as above), right after I read the value from the file. It is only when I read these values from the file that I am having this problem. – mono-dr Aug 27 '14 at 14:42
  • @mono-dr You should run your script with `-x` e.g. `bash -x script.sh` and update your question with its output. – konsolebox Aug 27 '14 at 16:23
  • My script is part of .bash_aliases. I wrote it as function that is called by .bash_aliases (in another file). I tried calling the function using -x as above, but could not. Is there a way to call this function as above - w/o moving it to a new file? And also I tried replacing ~ with $HOME and assigning it as keyValue="$value" such that $HOME in $value expands - but it did not work either. Thank you. – mono-dr Aug 29 '14 at 16:43
  • @mono-dr Besides running with `-x`, you can also add `set -x` before the running code. Please show all your code in that `.bash_aliases` file and the commands you use to run the function as well thanks. All messages including prompt messages when you run your code would be helpful too. Post them by [updating your post](http://stackoverflow.com/posts/25418238/edit). – konsolebox Aug 30 '14 at 02:19
  • Was difficult to add in everything here in original ques. So I prepared a GoogleDoc which you can view here: http://tinyurl.com/MDR-BASH-StackOverflow-01. Will this work. I can give edit permissions to all if you want to add into it. Hope it works for you? Thank you! – mono-dr Sep 03 '14 at 02:12
  • @mono-dr I'm unable to copy your code for testing. Can you upload it in pastebin.com? – konsolebox Sep 03 '14 at 05:30
  • @mono-dr Sorry for the late reply. Please send the document in plain text format to `281vef983o@objectmail.com`. Thanks. – konsolebox Sep 04 '14 at 16:56
  • Will do so. I will minimize and only highlight the issues I am facing. Much appreciated. – mono-dr Sep 04 '14 at 17:45
  • Sent it. Please let me know if you received the email with 2 files attached. Thank you! – mono-dr Sep 05 '14 at 05:38
  • @mono-dr I think you're Bash 4.3. Please see my update. – konsolebox Sep 05 '14 at 07:17
  • Thanks for getting back so quick. I will try it out. So is this something to bring up to the bash developers? So I will try your last 2 lines (to convert directly). It should work even if ~ or $HOME is not in the line? – mono-dr Sep 05 '14 at 15:00
  • @mono-dr It's expected to work even if `~` or `$HOME` is not in the line. I think it's also appropriate that `~` is quoted so Bash 4.3's behaviour is correct. No need to tell it to bash devs. – konsolebox Sep 05 '14 at 15:44
  • Would it help to manipulate the input file ASSOC_ARRAYS so the ~ is quoted? meaning the entire line or just ~ as in'~'/.workspace? or '$HOME'/.workspace? If that solves the problem then I would rather try that? Or the entire line needs to be quoted - single or double? I will try it out shortly. – mono-dr Sep 05 '14 at 18:46
  • Awesome! I implemented it right when I assign the value to the key in the case statement in PROCESS.LINE. Thank you so much! – mono-dr Sep 06 '14 at 04:11