-1

I am creating a bash function that should return true/false if a specified symlink refers to specified target. I based myself on https://unix.stackexchange.com/a/192341/40237

However, I am having trouble getting readlink to work as I want:

is_symlink_to () {
# $1 = symlink / $2 = symlink target
    echo "arg1: $1 and arg2: $2"
    echo readlink arg 1 is: $(readlink -v $1 )   # -v for troubleshooting
    if  [ "$(readlink -- $1)" = $2 ]; then
        echo "$1 is a symlink to $2"
        return 0;
    else
        return 1;
   fi
}

...

if is_symlink_to "~/$file" "$dir/$file" ; then
    echo "is already symlinked"
else
   ...
fi

Question: Why does readlink -v return No such file or directory?

arg1: ~/.bash_profile and arg2: /home/me/dotfiles/.bash_profile
readlink: '~/.bash_profile': No such file or directory
readlink arg 1 is:

If I run readlink from a bash shell, it works fine:

me@mango:~/dotfiles$ readlink -v ~/.bash_profile
/home/me/dotfiles/.bash_profile
| improve this question | | | | |
  • @ilkkachu: I've updated my post to include the function call – Rabarberski Nov 11 '19 at 10:46
  • 2
    The answer of @UmairKhan looks right. Please try what happens if you remove the double quotes around the first variable of your call to is_symlink_to, and try if instead is_symlink_to ~/"$file" "$dir/$file" works. – AdminBee Nov 11 '19 at 11:07
  • @AdminBee: Works perfect now. Thanks! I hadn't expected the tilde to be the problem. If you put it in an answer, I'll accept it. – Rabarberski Nov 11 '19 at 11:39
  • See also [ "$file1" -ef "$file2" ] to check whether two paths refer to the same file (after symlink resolution) – Stéphane Chazelas Nov 11 '19 at 12:24
  • Remember to quote your parameter expansions! (but not ~) and use -- to mark the end of options for readlink (readlink -v -- "$file") – Stéphane Chazelas Nov 11 '19 at 12:26
1

As pointed out by @UmairKhan, the tilde expansion doesn't work inside double-quotes, so the statement

if is_symlink_to "~/$file" "$dir/$file" ; then

would look for a file (in your example) .bash_profile inside a directory literally named ~ inside your current directory, instead of inside your home directory.

It should work if you only enclose the actual "bash variable part" in parentheses, as in

if is_symlink_to ~/"$file" "$dir/$file"; then

Although completely omitting the double parentheses around your first argument would also work (is_symlink_to ~/$file "$dir/$file") , this is not advisable as it might stumble upon filenames with special characters.

| improve this answer | | | | |
1

The ~ in "~/$file" is being treated literally, due to the surrounding quotes.

In script form, this is better represented as:

"${HOME}/$file"

The ${HOME} variable is equivalent to ~ and will expand within double quotes.

| improve this answer | | | | |
  • Thanks. I've accepted AdminBee's answer, but using the $HOME variable is indeed how I finally handled it. – Rabarberski Nov 11 '19 at 12:13

Not the answer you're looking for? Browse other questions tagged or ask your own question.