how to extract file location of a sourced script within the script - linux

In a script which I call with the "source" command under linux I want to determine the directory where the script is located. Assuming there is a script under $HOME/foo/bar/sourceme and i call the script from $HOME with source $HOME/foo/bar/sourceme I would like to extract within the script that it is located under $HOME/foo/bar. I know that it is possible without source by using
set _dir = `dirname $0`
setenv MY_DIR = `cd $_dir ; pwd`
but this doesn't work when i use a source.

Related

Absolute and relative path in Linux

I am writing a shell script which runs pwd command and uses its output for some others tasks performed by the script. The script is working totally fine when I go to the particular directory and run it. But when I am trying to run the script from some other location by giving the full path of the script, I am not getting the desired output as pwd command gives current directory's path. How can I solve this issue? How can I write something that will hold correct irrespective of where I run the script from?
The same issue is being faced when I am using ..to get to previous directory. I want the script to take path with respect to its location instead of path where the script is being run. Please let me know if there are some other details required.
You can use $0 to extract script and then combine it with pwd
$ cat abc.sh
echo $0
DIR1=$(dirname `pwd`/$0)
echo $DIR1
DIR2="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
echo $DIR2
There are other ways to achieve it in all cases:
Reliable way for a bash script to get the full path to itself?
Getting the source directory of a Bash script from within

Include binary from relative path in bash script

I have a project/bin/ directory which is not included in the PATH. It contains
the binaries project/bin/one and project/bin/two.
A bash script is located in project/shell/script1/run.sh. Now, I want to use the binary from the project/bin folder in the project/shell/script1/run.sh script. I would like to have a global script which can be sourced, and include those binaries automatically.
So, I created a script project/bin/load_bin:
#!/usr/bin/env bash
$local_bin_one='./one'
$local_bin_two='./two'
In my project/shell/script1/run.sh I execute the script:
#!/usr/bin/env bash
source '../../bin/load_bin'
However, when I try to use $local_bin_one I get a file not found error. This is because the $local_bin_one points to ./one instead of ../../bin/one.
Question: How can I find the path of the script that is calling source '../../bin/load_bin' from the project/bin/load_bin script itself?
You can get the path of a Bash script this way:
${0%/*}
That is, take $0 (argv[0], the full path and filename the script was invoked with), and strip off the last slash and what comes after that (equivalent to $(dirname "$0")).
You can then do this:
mydir=${0%/*}
source "$mydir/../../bin/load_bin"
Or you can even do this:
cd ${0%/*}
source '../../bin/load_bin'

Execute bash script from one into another directory?

I have 3 directories:
/A/B/C and 1 bash script in C directory.
How can I execute this bash script from A into in C directory.
I understand from your comments that you want your script to have its current working directory to be in A/B/C when it executes. Ok, so you go into directory A:
cd A
and then execute script.sh from there:
(cd B/C; ./script.sh)
What this does is start a subshell in which you first change to the directory you want your script to execute in and then executes the script. Putting it as a subshell prevents it from messing up the current directory of your interactive session.
If it is a long running script that you want to keep in the background you can also just add & at the end like any other command.
Whenever I want to make sure that a script can access files in its local folder, I throw this in near the top of the script:
# Ensure working directory is local to this script
cd "$(dirname "$0")"
It sounds like this is exactly what you're looking for!
Assuming /A/B/C/script.sh is the script, if you're in /A, then you'd type ./B/C/script.sh or bash B/C/script.sh or a full path, /A/B/C/script.sh. If what you mean is that you want that script always to work, then you'll want to add it to your PATH variable.
Go to A, then run your script by providing the path to it:
cd /A
bash B/C/somescript.sh
You could also add C to your PATH variable, making it runnable from anywhere
(i.e. somescript.sh, without the path)
If you want to access the directory the script is stored in, within the script, you can use this one-liner:
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
or simply dirname. Taken from this thread. There are many more suggestions there.
The easy way to make your script execute within C is to simply be in that folder.

How to handle change in the $PWD value in shell script?

I have a shell script executed by a tool.
When it is executed by a this tool then the value of $PWD is set by that tool.
However when I executed the script manually the value of $PWD the current directory of script.
Now I'm using this $PWD environmental variable to locate different file location in the script.
But when I execute it manually the file path get changed and it give unexpected results.
Any suggestion how can I handle this change in the value of $PWD while executing the script manually or by that tool?
If you need access to the directory where the script itself is located, in bash you can use
script_dir=$(readlink -f ${0%/*})
It takes the relative path to the script ($0), cuts off the script name and transforms it to a full path.

How to include file in a bash shell script

Is there a way to include another shell script in a shell script to be able to access its functions?
Like how in PHP you can use the include directive with other PHP files in order to run the functions that are contained within simply by calling the function name.
Simply put inside your script :
source FILE
Or
. FILE # POSIX compliant
$ LANG=C help source
source: source filename [arguments]
Execute commands from a file in the current shell.
Read and execute commands from FILENAME in the current shell. The
entries in $PATH are used to find the directory containing FILENAME.
If any ARGUMENTS are supplied, they become the positional parameters
when FILENAME is executed.
Exit Status:
Returns the status of the last command executed in FILENAME; fails if
FILENAME cannot be read.
Above answers are correct, but if you run script in another folder, there will be some problem.
For example, a.sh and b.sh are in same folder,
a use . ./b.sh to include b.
When you run script out of the folder, for example, xx/xx/xx/a.sh, file b.sh will not found: ./b.sh: No such file or directory.
So I use
. $(dirname "$0")/b.sh
Yes, use source or the short form which is just .:
. other_script.sh
Syntax is source <file-name>
ex. source config.sh
script - config.sh
USERNAME="satish"
EMAIL="satish#linuxconcept.com"
calling script -
#!/bin/bash
source config.sh
echo Welcome ${USERNAME}!
echo Your email is ${EMAIL}.
You can learn to include a bash script in another bash script here.
In my situation, in order to include color.sh from the same directory in init.sh, I had to do something as follows.
. ./color.sh
Not sure why the ./ and not color.sh directly. The content of color.sh is as follows.
RED=`tput setaf 1`
GREEN=`tput setaf 2`
BLUE=`tput setaf 4`
BOLD=`tput bold`
RESET=`tput sgr0`
Making use of File color.sh does not error but, the color do not display. I have tested this in Ubuntu 18.04 and the Bash version is:
GNU bash, version 4.4.19(1)-release (x86_64-pc-linux-gnu)

Resources