23

I'm creating a bash script to check if a symlink target matches a specific path so, in case it doesn't match, script removes the symlink. I've tried with readlink:

#!/bin/env bash

target_path=$HOME/Code/slate/.slate.js

if [ `readlink $HOME/.slate.js` == "$target_path" ]; then
    rm -rf "$HOME/.slate.js"
fi

but it doesn't work:

%source test
test:5: = not found
Alex Guerrero
  • 2,109
  • 1
  • 19
  • 28

2 Answers2

28

You should use double quotes as follow when you compare strings (and yes, the output of readlink $HOME/.slate.js is a string):

[ "$(readlink $HOME/.slate.js)" = "$target_path" ]
Radu Rădeanu
  • 2,642
  • 2
  • 26
  • 43
7

In case $target_path does not match the link text exactly, you can check that they are, in fact equivalent (regardless of name). But since a hardlink is preferable you might want to check that case, too (see below).

A more generic solution is:

[ "$(readlink $HOME/.slate.js)" -ef "$target_path" ]

Or, as in your example:

target_path=$HOME/Code/slate/.slate.js

if [ "`readlink $HOME/.slate.js`" -ef "$target_path" ]; then
    rm -rf "$HOME/.slate.js"
fi

But that all assumes that your $HOME/.slate.js is a symbolic link. If it is a hard link (which is preferable, when possible), then it is simpler:

 … [ "$HOME/.slate.js" -ef "$target_path" ] …

Maybe something like (check whether it is a symlink, if so, then check that link matches target; otherwise check whether the files same—either a hard link or actually the same file):

 … [ \( -L "$HOME/.slate.js" -a "`readlink $HOME/.slate.js`" -ef "$target_path" \) \
     -o \( "$HOME/.slate.js" -ef "$target_path" \) ] …

You should also check whether the file is, in fact, the same file (and not a hard link), otherwise you will delete the one and only copy.

Jason
  • 920
  • 8
  • 19
bill.lee
  • 2,207
  • 1
  • 20
  • 26