1

This code from Stack Overflow is to get the pathname to the parent directory of a script inside the script, even if the script is run via a symlink to it:

if [ -L $0 ] ; then
    DIR=$(dirname $(readlink -f $0)) ;
else
    DIR=$(dirname $0) ;
fi ;

Is the above code equivalent to

DIR=$(dirname $(readlink -f $0)) ;

i.e. is there really a need to test if $0 is a symlink, and run different commands if yes and if no?

Why not just use $(dirname $(readlink -f $0)) regardless of whether $0 contains symlink or not?

Specifically, if $0 contains symlink, then it is perfect to use $(dirname $(readlink -f $0)).

if $0 is not a symlink, then it seems perfect to me to just use $(dirname $(readlink -f $0)):

  • $(readlink -f $0) returns the absolute path of $0, and $(dirname $(readlink -f $0)) returns the absolute path to the parent directory of $0

  • $(dirname $0) returns a path to the parent of $0, whether the return is an absolute or relative path depending on if $0 is an absolute or relative path.

  • I don't think whether the value of DIR is an absolute or relative path is important in the original code, because in either case, the value of DIR refers to the parent directory of $0. So are $(dirname $(readlink -f $0)) and $(dirname $0) equivalent in the original code?

Thanks.

1
  • readlink -f appears to allow you to specify a format on MacOS rather than 'force'. If the desired behavior is to get the real path of the given file, consider using realpath if available or readlink "$0" || echo "$0" for something more portable.
    – Beefster
    Commented Oct 4, 2021 at 16:31

2 Answers 2

2

You should use "$0" and dirname "$()".

The commands are not equivalent because the shell test affects only the last component in the path but readlink -f affects all path levels.

mkdir physdir
touch physdir/file
ln -s physdir symlink
test -L symlink/file ; echo $?
    1
test -L symlink ; echo $?
    0
dirname symlink/file
    symlink
dirname "$(readlink -f symlink/file)"
    /crypto/home/hl/tmp/stackexchange/readlink/physdir

So for relative paths the output is quite different but even for absolute paths the symlink directories within differ.

9
  • Thanks. Still not sure about my question "If $0 is not a symlink, then are $(dirname $(readlink -f $0)) and $(dirname $0) equivalent?" see my edit
    – Tim
    Commented Mar 21, 2018 at 15:42
  • What do you mean by "the shell test affects only the last component in the path" and "readlink -f affects all path levels"?
    – Tim
    Commented Mar 21, 2018 at 16:06
  • @Tim See my edit. Commented Mar 22, 2018 at 10:58
  • Thanks. I see. I just clarified my question, see my edit.
    – Tim
    Commented Mar 23, 2018 at 20:10
  • My question is actually: Why not just use $(dirname $(readlink -f $0)) regardless of whether $0 contains symlink or not?
    – Tim
    Commented Mar 24, 2018 at 15:53
2

I think whether there's a difference or not depends on the exact flavor of unix that you're using. On OSX for example, readlink doesn't have a -f flag and states:

If the given argument is not a symbolic link, readlink will print nothing and exit with an error

If you know that your OS supports the -f flag then there shouldn't be any difference.

In fact the -m flag might be the most flexible one to use.

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .