2

About the situation:

I have a symbolic link named mycommand within $PATH. It links to a file called mycommand.sh elsewhere. That file needs another file, lets call it mycommand2.sh:

somedir
|-mycommand.sh
|-mycommand2.sh

when directly running ./mycommand.sh the other file is found. When running mycommand it isn't. Reason: Within mycommand.sh the other file is called as ./mycommand2.sh.

How can I make mycommand working without changing all relative directories to absolute ones?

1
  • Where are you issuing mycommand in the two cases? A symbolic link from a directory will not change cwd, so it should work identically if run from somedir. That hidden dependency is undesirable, though: could you also link mycommand2.sh from the same directory as mycommand? Oct 4, 2020 at 9:58

1 Answer 1

2

The problem is not caused by the symlink.

If mycommand.sh calls ./mycommand2.sh, it expects its current working directory to be somedir. The current working directory is not related to how the command was named or invoked. It's a property of processes that is set with the chdir() system call or the cd builtin command in shells.

If you did:

cd /path/to/somedir
mycommand

mycommand aka mycommand.sh would still find ./mycommand2.sh in the current directory.

For mycommand.sh to find mycommand2.sh regardless of the working directory its is being called from, it would need to be modified like:

#! /bin/sh -
mydir=$(dirname -- "$0")
"${mydir%/}/mycommand2.sh"

Or if mycommand.sh does require its working directory to be somedir:

#! /bin/sh -
mydir=$(dirname -- "$0")
CDPATH= cd -P -- "$mydir" || exit

./mycommand2.sh

And that's when using a symlink would cause problems, as if invoked as mycommand, dirname -- "$0" would return the dirname of the mycommand symlink, not that of the mycommand.sh script.

To work around it, you'd modify mycommand.sh as:

#! /bin/sh -
mydir=$(dirname -- "$(readlink -f -- "$0")")
"${mydir%/}/mycommand2.sh"

Where readlink -f (not a standard command but pretty common) would resolve all symlinks. That assumes mycommand.sh itself is not a symlink to a script in a different directory.

If you can't or would rather not modify that script, another approach would be to create a mycommand script instead of symlink that does:

#! /bin/sh -
cd /path/to/somedir &&
  exec ./mycommand.sh "$@"

You must log in to answer this question.

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