This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
In the bash script how do I know the script file name?
I often need the file system of a bash script to reference other needed resources. Normally use the following code in line after the shebang line. It sets a variable called 'scriptPos' contains the current path of the scripts
scriptPos=${0%/*}
It works fine, but is there something more intuitive to replace the shell expansion?
There's dirname but it requires a fork:
scriptPos=$(dirname "$0")
One option is
scriptPos=$(dirname $0)
which comes at the cost of an extra process, but is more self-descriptive. If the script is in the current directly, the output differs (for the better, in my opinion):
#!/bin/bash
scriptPos=$(dirname $0)
echo '$0:' $0
echo 'dirname:' $scriptPos
echo 'expansion:' ${0%/*}
$ bash tmp.bash
$0: tmp.bash
dirname: .
expansion: tmp.bash
UPDATE: An attempt to address the shortcomings pointed out by jm666.
#!/bin/bash
scriptPos=$( v=$(readlink "$0") && echo $(dirname "$v") || echo $(dirname "$0") )
Related
This question already has an answer here:
Find "command not found" when executed in bash loop
(1 answer)
Closed 4 years ago.
When running this script:
#!/bin/sh -ex
if [[ $# -ne 1 ]]; then
echo "./import-public-ssh-key.sh <absolute path to public key>"
exit 1;
fi
PATH=$1
KEY=$(basename ${PATH})
I get:
./import-public-ssh-key.sh: line 9: basename: command not found
without the subshell basename works:
$ basename /Users/mles/.ssh/id_rsa.pub
id_rsa.pub
Why is basename not working in the subshell? I'm on a mac if this is relevant.
You reset the PATH. Don't do that. The shell searches all the directories listed in PATH, and you have changed it so that PATH no longer contains the directory that contains basename.
This question already has answers here:
How to go to each directory and execute a command?
(12 answers)
Closed 5 years ago.
I'm currently trying to write a script which will cd to a directory and execute a python script if it matches a predefined string to the directory name. I need the code to change to a directory with the string 'batch' in it and execute the script. The most useful tool would probably be the case statement, but I can't get it to work for some reason. I'm fairly new to bash scripting, so i'm not really sure why this isn't working.
Here's my code:
#!/bin/bash
dir_string="batch"
workingdir=$PWD
for dir in *;do
echo "$dir"
if [[-d "$dir"]]; then
case "$dir_string" in
$dir)
cd $workingdir/$dir
for i in *;do
execute python script
done
;;
*)
echo "Can't find appropriate directories."
;;
esac
fi
done
Any help is appreciated!
What you are trying to achieve with your script, can be achieve with find:
#!/bin/bash
dir_string="batch"
workingdir=$PWD
for dir in $(find "$workingdir" -type d|grep $dir_string)
do
(cd "$dir" && execute python script)
done
This question already has answers here:
How do I get the directory where a Bash script is located from within the script itself?
(74 answers)
Closed 6 years ago.
I have a shell script here:
/node_modules/.bin/exec.sh
in the exec.sh script, I want to obtain the path of the directory's parent directory that the script is contained in (not pwd/cwd!). I can obtain the containing directory like so:
`dirname $0`
which will yield:
/node_modules/.bin
but I am looking to get at one directory higher, I just want to get
/node_modules
I am having trouble searching for the answer, my guess is:
`dirname $1`
but just a guess, not sure if that's right at all. Can anyone give an explanation of how to do this and how it works?
Run dirname twice (nested).
~$ dirname $PWD
/home
~$ dirname `dirname $PWD`
/
~$
I believe the answer is
$(dirname $(dirname "$0"))
don't forget about the double-quotes around "$0"
We now to find the directory of a shell script using dirname and $0, but this doesn't work when the script is inluded in another script.
Suppose two files first.sh and second.sh:
/tmp/first.sh :
#!/bin/sh
. "/tmp/test/second.sh"
/tmp/test/second.sh :
#!/bin/sh
echo $0
by running first.sh the second script also prints first.sh. How the code in second.sh can find the directory of itself? (Searching for a solution that works on bash/csh/zsh)
There are no solution that will work equally good in all flavours of shells.
In bash you can use BASH_SOURCE:
$(dirname "$BASH_SOURCE")
Example:
$ cat /tmp/1.sh
. /tmp/sub/2.sh
$ cat /tmp/sub/2.sh
echo $BASH_SOURCE
$ bash /tmp/1.sh
/tmp/sub/2.sh
As you can see, the script prints the name of 2.sh,
although you start /tmp/1.sh, that includes 2.sh with the source command.
I must note, that this solution will work only in bash. In Bourne-shell (/bin/sh) it is impossible.
In csh/tcsh/zsh you can use $_ instead of BASH_SOURCE.
Getting at the path to a running script in bash is trivial via the $0 variable. However, it doesn't work if you are being dotted in via another script, instead you will get the path to the calling script. Consider the example:
#!/bin/bash
# script1.sh
echo $(readlink -f $0)
...
#!/bin/bash
# script2.sh
. /tmp/script1.sh
echo $(readlink -f $0)
The output from the above script is:
/tmp/script2.sh
/tmp/script2.sh
However, if $0 in a dotted-in script emitted the path to that script, the output would instead be:
/tmp/script1.sh
/tmp/script2.sh
How can I get that correct value?
To overcome this (specific to bash) you can use ${BASH_SOURCE[0]}
#!/bin/bash
# script1.sh
real_dollar_zero=${BASH_SOURCE[0]}
echo $(readlink -f $real_dollar_zero)
Now the output is:
/tmp/script1.sh
/tmp/script2.sh
Viola! - The strung musical instrument often confused with a violin!