I have this simple script to use with seventh sense (it's a lone wolf gamebook reader/player):

GAME_PATH=$(dirname "$(readlink -f "$0")")
SEVENTH_SENSE_PATH=$(echo ~)"/.wine/drive_c/users/"$(whoami)"/Documents"
ln -s -f "$GAME_PATH/Lone Wolf/books" "$SEVENTH_SENSE_PATH/Seventh Sense"
cd "$GAME_PATH/Lone Wolf"
wine Lone\ Wolf.exe

It's very simple, only moving a directory inside the folder to the location that this windows program expects it on the wine dir - but that is not the problem.

ln here works the first time (it creates a symlink to books named Seventh Sense inside the Documents folder of the wine user. The problem is, the second time it makes a books symlink inside the folder that the Seventh Sense symlink points to (ironically, exactly the original books folder), when run twice.

It causes no harm, but it seems like an obvious bug that is escaping me.

(books is a folder (inside the Lone Wolf folder that is at the same level as the script)).

  • I just realized it's probably because the First time the folder "Seventh Sense" doesn't exist, so ln assumes it is to be the name of the symlink - if it already does, it assumes it is to create one with the default name ("books") inside the directory... How can i avoid this behavior? Need i delete it always? I thought -f was supposed to do that ("remove existing destination files"). – i30817 Jul 25 '11 at 14:59
  • As per the comment above, i RTFM, and realized -f is not enough, it must use -n also to not dereference the final symlink. Question answered! – i30817 Jul 25 '11 at 15:03
  • Post it as an answer and you can accept it – Michael Mrozek Jul 25 '11 at 15:12
  • @i30817: Glad you got it fixed. Please add an answer and (after the 48hr timeout) mark it as accepted so people can see how this was solved. You might need to wait for a timeout as a new user before you can post an answer to your own question, but please do! – Caleb Jul 25 '11 at 15:13

ln, like cp and mv, behaves differently depending on whether the destination is an existing directory (including a symbolic link to one). If it isn't, then the source is copied/moved/linked to the desintation name. If the destination is an existing directory, the source is copied/moved/linked to a file of the same base name as the source, under the destination directory.

With GNU ln (as found under Linux), use the -n option to overwrite the destination rather than writing under it when the destination is a symbolic link to a directory.

ln -snf "$GAME_PATH/Lone Wolf/books" "$SEVENTH_SENSE_PATH/Seventh Sense"

Alternatively, you can test if the destination is a directory, and not recreate it if exists.

[ -d "$SEVENTH_SENSE_PATH/Seventh Sense"/. ] ||
ln -s "$GAME_PATH/Lone Wolf/books" "$SEVENTH_SENSE_PATH/Seventh Sense"

Alternatively, you can remove the target first and create it unconditionally.

rm -f "$SEVENTH_SENSE_PATH/Seventh Sense"
ln -s "$GAME_PATH/Lone Wolf/books" "$SEVENTH_SENSE_PATH/Seventh Sense"

This happens because the second time you run your script, the link exists and it points to a directory. So it puts the new link inside that directory. You can use something like this:

if test -e "$SEVENTH_SENSE_PATH/Seventh Sense"
 echo " link already exists"
 ln -s -f "$GAME_PATH/Lone Wolf/books" "$SEVENTH_SENSE_PATH/Seventh Sense"

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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