dagnelies
dagnelies

Reputation: 5321

bash scripting: how to find the absolute path of "symlink/.."?

Given two files:

generic/scripts/hello.sh
parent/scripts -> generic/scripts

Upon calling parent/scripts/hello.sh from any location, I would like (in the script) to find the full path of the parent directory. In this case parent.

The main issue is that parent/scripts/.. refers to generic in unix. On the other hand, everything involving regexes is not generic and may be error prone.

Solutions that don't work:

`dirname $0`/..
realpath  `dirname $0`/..
readlink -f `dirname $0`/..
`cd *something*/..; pwd`
`perl ... abs_path(...)`

All these will point to generic and not parent because of the symbolic link.

Everything involving regular expressions are not adaptable/generic, may fail for more complexes paths. There might be other .. and symlinks in the path, you want the grand-parent, it's a directory name involving .., you call it via $PATH...

Moreover, I would like it to work in any case, even when it is called via $PATH.

Any simple safe solution for this simple problem? I mean it's just getting the parent directory after all!

What I used:

dir=$( dirname $( cd `dirname $0` >/dev/null; pwd ) )

Dunno if it is perfect but it seems to behave as expected.

Upvotes: 8

Views: 13187

Answers (6)

imme
imme

Reputation: 645

in bash you could do some string manipulation on $PWD if that variable is available.

For pathname of parent directory, use:

${PWD%/*}

Other examples :

me@host:/tmp/bash_string/ma ni-pu_la/tion$ echo -e \
"\$PWD or \${PWD} : " $PWD \
"\n\${PWD##/*}     : " ${PWD##/*} \
"\n\${PWD##*/}     : " ${PWD##*/} \
"\n\${PWD#/*}      : " ${PWD#/*} \
"\n\${PWD#*/}      : " ${PWD#*/} \
"\n\${PWD%%/*}     : " ${PWD%%/*} \
"\n\${PWD%%*/}     : " ${PWD%%*/} \
"\n\${PWD%/*}      : " ${PWD%/*} \
"\n\${PWD%*/}      : " ${PWD%*/} \
"\n" # Gives :
$PWD or ${PWD} :  /tmp/bash_string/ma ni-pu_la/tion 
${PWD##/*}     :  
${PWD##*/}     :  tion 
${PWD#/*}      :  tmp/bash_string/ma ni-pu_la/tion 
${PWD#*/}      :  tmp/bash_string/ma ni-pu_la/tion 
${PWD%%/*}     :  
${PWD%%*/}     :  /tmp/bash_string/ma ni-pu_la/tion 
${PWD%/*}      :  /tmp/bash_string/ma ni-pu_la 
${PWD%*/}      :  /tmp/bash_string/ma ni-pu_la/tion

Upvotes: 0

User
User

Reputation: 14853

I call my scipt with this: ../script1 and it has a relative call to ../relative/script2

`(cd $0/.. && pwd)`/relative/script2

is in script1

Upvotes: 0

PaulMurrayCbr
PaulMurrayCbr

Reputation: 1260

pushd $(dirname $0)
FOO=$(pwd)
popd

That gives you the absolute path of the directory that the script is running in.

Upvotes: 1

jlliagre
jlliagre

Reputation: 30803

Try this:

basename $(dirname $(dirname $0))

or perhaps just

$(dirname $(dirname $0))

It is unclear if you want parent alone or its full path.

Upvotes: 5

Op De Cirkel
Op De Cirkel

Reputation: 29463

I would recommend 1) use pwd -P which will always give you the physical path, and then navigate with relative path to the other palce This is most safe.

2) use pwd -L

Upvotes: 1

patapizza
patapizza

Reputation: 2398

What about this:

echo `cd .. && pwd`

Upvotes: -3

Related Questions