7

Possible Duplicate:
Reliable way for a bash script to get the full path to itself?

I have bash script test.sh which use functions from another search.sh script by following lines:

source ../scripts/search.sh
<call some functions from search.sh>

Both scripts are located in git repository. search.sh in <git_root>/scripts/ directory, test.sh is located in the same directory (but, generally speaking, could be located anywhere inside <git_root> directory - I mean I can't rely on the following source search.sh approach ).

When I call test.sh script from <git_root>/scripts/ everything works well, but as soon as I change current working directory test.sh fails:

cd <git_root>/scripts/
./test.sh         //OK
cd ..
./scripts/test.sh //FAILS
./scripts/test.sh: line 1: ../scripts/search.sh: No file or directory ...

Thus what I have:

  1. Relative path of search.sh script towards <git_root> directory

What I want: To have ability to run test.sh from anywhere inside <git_root> without errors.

P.S.: It is not possible to use permanent absolute path to search.sh as git repository can be cloned to any location.

Community
  • 1
  • 1
likern
  • 3,744
  • 5
  • 36
  • 47
  • It is not duplicate. I tried methods from this link. But it's not my case as here I do not need to get path of my `test.sh` script. – likern Jan 09 '13 at 15:02
  • Perhaps I'm stating the obvious, but if you currently `source` a relative path from the current directory, sourcing a relative path from the script's path seems like a good improvement. The only complication is if the user moves the script to a different location altogether, but I cannot imagine how you would fix that, other than with an environment variable. – tripleee Jan 09 '13 at 16:07
  • If the `search.sh` script is in the same directory as `test.sh`, then finding the path that `test.sh` is in will most definitely help, as then you use that path to find your other script. – Some programmer dude Jan 09 '13 at 16:55

4 Answers4

3

If both the scripts are in the same directory, then if you get the directory that the running script is in, you use that as the directory to call the other script:

# Get the directory this script is in
pushd `dirname $0` > /dev/null
SCRIPTPATH=`pwd -P`
popd > /dev/null

# Now use that directory to call the other script
source $SCRIPTPATH/search.sh

Taken from the accepted answer of the question I marked this question a duplicatre of: https://stackoverflow.com/a/4774063/440558

Community
  • 1
  • 1
Some programmer dude
  • 400,186
  • 35
  • 402
  • 621
1

You could do this:

# Get path the Git repo
GIT_ROOT=`git rev-parse --show-toplevel`

# Load the search functions
source $GIT_ROOT/scripts/search.sh

How get Git root directory!

Or like @Joachim Pileborg says, but you have to pay attention that you must know the path of this one to another script;

# Call the other script
source $SCRIPTPATH/../scripts/search.sh
# Or if it is in another path
source $SCRIPTPATH/../scripts/seachers/search.sh

The Apache Tomcat scripts use this approach:

# resolve links - $0 may be a softlink
PRG="$0"

while [ -h "$PRG" ] ; do
  ls=`ls -ld "$PRG"`
  link=`expr "$ls" : '.*-> \(.*\)$'`
  if expr "$link" : '/.*' > /dev/null; then
    PRG="$link"
  else
    PRG=`dirname "$PRG"`/"$link"
  fi
done

PRGDIR=`dirname "$PRG"`

Any way, you have to put this snippet on all scripts that use other scripts.

Community
  • 1
  • 1
  • Does any other way, without using git features as in reliable code I must use check of existence of `git` command. I mean in every new script I must use some duplicated code: check `git` existence, getting `GIT_ROOT`, etc... – likern Jan 09 '13 at 15:07
  • What if the user isn't in the Git repository itself? Is there a way to find a Git local repository? – David W. Jan 09 '13 at 15:09
  • @DavidW. the most reliable way of finding a Git local repository is to move upwards in the directory structure until you find a `.git` directory or hit some defined directory, e.g., `$HOME`, `/`, etc. – Ian Stapleton Cordasco Jan 09 '13 at 15:24
  • @sigmavirus24 I took it from the OP that the directory he is using may be outside of the Git repository itself. For example, he's in `$HOME/bin`, but the Git repo is in `$HOME/work/git_repo`. – David W. Jan 09 '13 at 15:37
  • From OP: `Both scripts are located in git repository.` ... `What I want: To have ability to run test.sh from anywhere inside without errors.` – Ian Stapleton Cordasco Jan 09 '13 at 15:46
  • @user966467, If you clone your Git repo you have git command, simple that! – Rodrigo Catto Jan 09 '13 at 16:59
  • @user966467, you can do as the Scripts Apache Tomcat (startup.sh, catalina.sh, ...) -> [snippet](http://pastie.org/private/avdgijufbaoakvkhxcwt5w) – Rodrigo Catto Jan 09 '13 at 17:26
1

Is there a way to identify this Git repository location? An environment variable set? You could set PATH in the script itself to include the Git repository:

 PATH="$GIT_REPO_LOCATION/scripts:$PATH"
 . search.sh

Once the script is complete, your PATH will revert to its old value, and $GIT_REPO_LOCATION/scripts will no longer be part of the PATH.

The question is finding this location to begin with. I guess you could do something like this in your script:

GIT_LOCATION=$(find $HOME -name "search.sh" | head -1)
GIT_SCRIPT_DIR=$(dirname $GIT_LOCATION)
PATH="$GIT_SCRIPT_DIR:$PATH"
. search.sh

By the way, now that $PATH is set, I can call the script via search.sh and not ./search.sh which you had to do when you were in the scripts directory, and your PATH didn't include . which is the current directory (and PATH shouldn't include . because it is a security hole).

One more note, you could search for the .git directory too which might be the Git repository you're looking for:

GIT_LOCATION=$(find $HOME -name ".git" -type d | head -1)
PATH="$GIT_LOCATION:$PATH"
. search.sh
David W.
  • 105,218
  • 39
  • 216
  • 337
  • But how to avoid problems with similar git repositories. There is no guarantee that someone did `git clone first-git-repo` and then `git clone second-git-repo`. Also in general case this solution can take too much time for searching this git repository. Also in general case we should use not only `$HOME` dir, but `/ (root)` dir. – likern Jan 09 '13 at 15:19
  • For these reasons I simplified the task. And even for this one can't find reliable approach ;) – likern Jan 09 '13 at 15:20
  • You're missing a closing parenthesis on the second line of the second code block. – Ian Stapleton Cordasco Jan 09 '13 at 15:21
  • @user966467 Okay, how do **you** know where that Git repository is located? However you find the location of that Git repository, you'll have to let your program know. – David W. Jan 09 '13 at 15:34
  • I suggest that I can use http://meta.stackexchange.com/questions/14237207/source-bash-script-to-another-one/14238266#comment19753159-14237207 which was mentioned by @Joachim Pileborg. – likern Jan 09 '13 at 15:47
0

For the people who would rather not use git's features for finding the parent directory. If you can be sure you'll always be running the script from within the git directory, you can use something like this:

git_root=""
while /bin/true ; do
    if [[ "$(pwd)" == "$HOME" ]] || [[ "$(pwd)" == "/" ]] ; then
        break
    fi

    if [[ -d ".git" ]] ; then
        git_root="$(pwd)"
        break
    fi

    cd ..
done

I haven't tested this but it will just loop back until it hits your home directory or / and it will see if there is a .git directory in each parent directory. If there is, it sets the git_root variable and it will break out. If it doesn't find one, git_root will just be an empty string. Then you can do:

if [[ -n "$git_root" ]] ; then
    . ${git_root}/scripts/search.sh
fi

IHTH

Ian Stapleton Cordasco
  • 26,944
  • 4
  • 67
  • 72