4

I made a symbolic link to an executable with

ln -s /usr/bin/mydir/myexec /usr/bin/myexec

When I executed myexec in Bash, it does not load the proper files which are located in the original myexec's directory.

Why is this happening and how can I solve it? I am on Fedora 15 x64.

2 Answers 2

4

Files that are called with relative paths in /usr/bin/mydir/myexec will be searched for relative to the current working directory from where the script is executed. Probably your script currently only works if it is executed from /usr/bin/mydir at the moment.

One way to solve this is by giving absolute paths to the included files (but then the script needs to be updated if the wanted files are ever moved), or you need to figure out the absolute path dynamically with readlink, e.g.

THISFILE=$(readlink -f -- "${0}")
THISDIR=${THISFILE%/*}
. "${THISDIR}/my_settings_file"
  • readlink -f will return the target of the symlink.
  • The ${THISFILE%/*} will return the target of the symlink with the portion including and after the last / removed, i.e. the path to the file in question.
  • ${THISDIR} now contains the absolute path to the file, and can be used as in line 3.

I assumed the question concerned a shell script. Other languages might have different methods.


Another way to solve it which avoids the problem more or less completely is to instead of symlinking the binary in your path, create a small script at /usr/bin/myexec that contains e.g.

#!/bin/sh
cd /usr/bin/mydir
./myexec
1

I disagree with @daniel-anderson. I don't think those solutions take arguments to the called program into account properly. Almost all executables treat path arguments as relative to the current directory, so even passing the arguments through is not going to work.

The only case in which a program will behave differently if it's called from a symlink is if it examines the 0th argument. I know of no way to work around this using a symlink. The simplest work around is creating an intermediate shell script in the form of:

#!/bin/sh
/path/to/executable/that/needs/0th/argument/to/be/actual/path $@

Note that if for some bizarre reason you need to give it a 0th argument that is not actually where it is, you may use exec -a like so:

#!/bin/bash
(exec -a /path/to/executable/to/fool /path/to/fool/executable/with $@)

Note that the "-a" argument may not be strictly POSIX spec, so I used bash specifically. Assuming you have a ~/bin folder in your path, the first (normal) case can be quickly accomplished like so:

echo -e '#!/bin/sh\n/path/to/executable $@' > ~/bin/shortcut
chmod 755 ~/bin/shortcut
shortcut

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .