Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Cann't obtain the script's directory from within sript itself by uisng the . command.

20 views
Skip to first unread message

Hongyi Zhao

unread,
Oct 29, 2017, 11:09:43 PM10/29/17
to
Hi all,

I have a script which has the following codes in it:

------ begin ------------------

#!/usr/bin/env bash

topdir=$(
cd -P -- "$(dirname -- "$(realpath -e -- "$0")" )" &&
pwd -P
)

echo $topdir


topdir=$(
cd -P -- "$(dirname -- "$0")" &&
pwd -P
)

echo $topdir
------ end ------------------

I save the above script with the name "obtain-script-dir.sh" under the
following directory: /home/werner/.profile.d/, you can see this from the
following info:

werner@debian-01:~/.profile.d$ pwd
/home/werner/.profile.d
werner@debian-01:~/.profile.d$ ls obtain-script-dir.sh
obtain-script-dir.sh

Now, I run the script with source, i.e., . command and bash respectively,
but I meet the following issues with the . command:


werner@debian-01:~$ . .profile.d/obtain-script-dir.sh
realpath: bash: No such file or directory
/home/werner
/home/werner

As you can see, it cann't find the realpath command, and the output
results are error.

But, the following command will run the script successfully:

werner@debian-01:~$ bash .profile.d/obtain-script-dir.sh
/home/werner/software/software-management/stow/oh-my-stow/stow-dir/pkg-
dir/home/werner/dot-profile.d
/home/werner/software/software-management/stow/oh-my-stow/stow-dir/pkg-
dir/home/werner/dot-profile.d

I'm very confused on this issue, any hints / notes will be highly
appreciated. Thanks in advance.

Regards
--
.: Hongyi Zhao [ hongyi.zhao AT gmail.com ] Free as in Freedom :.

Thomas 'PointedEars' Lahn

unread,
Oct 30, 2017, 8:18:32 AM10/30/17
to
Hongyi Zhao wrote:

> #!/usr/bin/env bash
^^^^^^^^^^^^
Pointless and counter-productive with a *shell* script. What if there is
only “/bin” and “/bin/bash”?

> topdir=$(
> cd -P -- "$(dirname -- "$(realpath -e -- "$0")" )" &&
> pwd -P
> )
>
> echo $topdir
^^^^^^^
Do not forget to quote variable references.

> […]
> werner@debian-01:~/.profile.d$ pwd
> /home/werner/.profile.d
> werner@debian-01:~/.profile.d$ ls obtain-script-dir.sh
> obtain-script-dir.sh
>
> Now, I run the script with source, i.e., . command and bash respectively,
> but I meet the following issues with the . command:
>
>
> werner@debian-01:~$ . .profile.d/obtain-script-dir.sh
> realpath: bash: No such file or directory
^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
> /home/werner
> /home/werner
>
> As you can see, it cann't find the realpath command, […]

_can’t_ (cannot)

Instead, the error message “bash: No such file or directory” is *created by*
the “realpath” command.

HTH

--
PointedEars

Twitter: @PointedEars2
Please do not cc me. /Bitte keine Kopien per E-Mail.

Ian Zimmerman

unread,
Oct 30, 2017, 12:28:12 PM10/30/17
to
On 2017-10-30 03:09, Hongyi Zhao wrote:

> cd -P -- "$(dirname -- "$(realpath -e -- "$0")" )" &&

> werner@debian-01:~$ . .profile.d/obtain-script-dir.sh
> realpath: bash: No such file or directory
> /home/werner
> /home/werner
>
> As you can see, it cann't find the realpath command, and the output
> results are error.

No, I cannot see that. That is not what the error message means.
Rather, realpath runs, and cannot find a bash file in the current
directory.

I think you misunderstand what realpath does. It does not simulate the
search for an executable along the PATH directory list such as a shell
does when it interprets a command. realpath just canonicalizes the name
of an existing file, which means, converts a name to an absolute one and
resolves any symlinks in it (including names of enclosing directories
which are really symlinks to directories).

What I think you might be trying to do is a hard, and maybe impossible,
problem in Unix: getting the full absolute name of a script from within
the script itself, without help from any extra configuration. Rather
than trying your luck in this game where many have failed before,
consider the easy and robust solution with an external configuration
file in a fixed location. For example, if your script lives in
/home/werner/bin, put this into /home/werner/pathconfig.sh:

WERNER_SCRIPT_DIR=/home/werner/bin

and then in your script (assuming the script runs as user werner):

. ~/pathconfig.sh

# now do something/anything with $WERNER_SCRIPT_DIR ...

--
Please don't Cc: me privately on mailing lists and Usenet,
if you also post the followup to the list or newsgroup.
Do obvious transformation on domain to reply privately _only_ on Usenet.

Hongyi Zhao

unread,
Oct 30, 2017, 9:09:02 PM10/30/17
to
On Mon, 30 Oct 2017 09:27:54 -0700, Ian Zimmerman wrote:

> No, I cannot see that. That is not what the error message means.
> Rather, realpath runs, and cannot find a bash file in the current
> directory.
>
> I think you misunderstand what realpath does. It does not simulate the
> search for an executable along the PATH directory list such as a shell
> does when it interprets a command. realpath just canonicalizes the name
> of an existing file, which means, converts a name to an absolute one and
> resolves any symlinks in it (including names of enclosing directories
> which are really symlinks to directories).

Thanks for your notes.

>
> What I think you might be trying to do is a hard, and maybe impossible,
> problem in Unix: getting the full absolute name of a script from within
> the script itself, without help from any extra configuration. Rather
> than trying your luck in this game where many have failed before,
> consider the easy and robust solution with an external configuration
> file in a fixed location. For example, if your script lives in
> /home/werner/bin, put this into /home/werner/pathconfig.sh:
>
> WERNER_SCRIPT_DIR=/home/werner/bin
>
> and then in your script (assuming the script runs as user werner):
>
> . ~/pathconfig.sh
>
> # now do something/anything with $WERNER_SCRIPT_DIR ...

Now, I trying the following code, and it seems that it will work:

pathconfig.sh
----------------------------
#!/usr/bin/env bash

topdir=$(
cd -P -- "$(dirname -- "$(realpath -e -- "${BASH_SOURCE[0]}")" )" &&
pwd -P
)

echo $topdir
---------------------------

All of the following commands will work on this script and give the same
result:

. /path/to/pathconfig.sh
source /path/to/pathconfig.sh
bash /path/to/pathconfig.sh
0 new messages