Run a shell script via a symbolic link from the directory containing the script itself

24,469

Solution 1

The shell will not change to another directory unless you tell it to. If you want your script to execute commands in a different directory, call cd from your script.

The path to the script is available as "$0". If the script is a symbolic link, that's the path to the symbolic link. If you want to get the final target of the symbolic link, call realpath (available on most but not all modern unices; it's available on Linux (both GNU and BusyBox), FreeBSD and Solaris 11, but not OSX).

cd "$(dirname "$(realpath "$0")")"

realpath is a relatively recent addition to GNU coreutils; if your version is too old, you can use readlink -f which is older. For non-GNU systems, if realpath isn't present then readlink may be but it typically only looks through one level of symbolic links, most readlink implementations don't have the -f option to do the full resolution.

Solution 2

You can derive the director in which the shell script exists from its $0 parameter. For example, you might use dirnameto do this within the script:

cd $(dirname "$0")

That assumes that your jar-file is in the same directory where the script it.

If you want to reference the script via a symbolic link (and still, assuming that the script and jar-file are in the same directory), you could do this by a more complicated script that would

  • find the pathname for $0 (simple if you use the default $PATH lookup), and
  • use a program such as readlink to read the symbolic link. That isn't POSIX, but exists on many Linux systems.
  • if you don't have readlink, it's possible with other workarounds (including reading the output of ls).
  • however you read the link, cd to that location.

Further reading:

Share:
24,469

Related videos on Youtube

Eray Erdin
Author by

Eray Erdin

Abilities Main Languages, Frameworks, Libraries and Tools Java Python Django JavaFX Desktop Applications Building and customizing JavaFX desktop applications. Restful Services Building Restful services using Django and its powerful environment. Linux System Administration Having a decent knowledge about Linux system architecture and how to manage it to accomplish things.

Updated on September 18, 2022

Comments

  • Eray Erdin
    Eray Erdin almost 2 years

    My desire is not to change directory then execute. I use a jar file and need to execute that. So I made a very basic shell script to do that.

    #!/bin/sh
    java -jar TreeForm.jar
    

    Then, I saved it as TreeForm, not TreeForm.sh. Next, I created a symbolic link as below:

    ln -s /opt/TreeForm/TreeForm /usr/bin/
    chmod +x /opt/TreeForm/TreeForm
    

    It is successfully created. However, when I run, I take the error below from JAVA.

    Error: Unable to access jarfile TreeForm.jar

    So, it seems shell script does not run its own directory or does not look into that, but works in current directory. I don't really want to modify my script file giving full path of TreeForm.jar. So I wanted to ask, is there a way to find a file relative to script file without changing the current path or adding path to PATH variable? Or is there any variable having the path of script, not the current one?

  • Eray Erdin
    Eray Erdin over 8 years
    I tried that, unfortunately it did not work. :(
  • Eray Erdin
    Eray Erdin over 8 years
    Well, I debugged it, I printed out pwd. Since I created a symlink, it sees the script in /usr/bin directory. Is there another solution? :/
  • Eray Erdin
    Eray Erdin over 8 years
    It seems there is no way to get the path of original script. It seems it will always get the path of symlink. So I accept this as valid answer. | Thanks for help. :)
  • Eray Erdin
    Eray Erdin over 8 years
    Working like a charm. The only thing is realpath is not built-in in Ubuntu 14.04. Thanks for edit and answer by the way. :)
  • Gilles 'SO- stop being evil'
    Gilles 'SO- stop being evil' over 8 years
    @ErayErdin Oh, I forgot realpath in GNU coreutils was that recent. You can use readlink -f instead.
  • Eray Erdin
    Eray Erdin over 8 years
    Now, it is perfectly fine. :)