How to check if a symlink target matches a specific path?
Asked Answered
C

2

24

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
Colocynth answered 8/11, 2013 at 13:34 Comment(4)
readlink $HOME/.slate.js might not return exactly the same as $target_path it might return something like Code/slate/.slate.js which is different from $target_pathWhoa
Does $HOME have a space in it, perchance?Dwinnell
echo both of them to checking actualy they are equalWhoa
test is probably not a good name for a shell script, as it's already a shell built-in and a binary in /bin (or /usr/bin)...Pyrometallurgy
B
29

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" ]
Beechnut answered 8/11, 2013 at 13:44 Comment(1)
(a) man 1 readlink: realpath (1) is a better command for canonicalization functionality. (b) [[ ]] (for Bash) is preferred over [ ].Gravelly
D
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.

Dele answered 9/4, 2015 at 18:46 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.