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

How do I convert a filename to absolute in bash?

65 views
Skip to first unread message

Alan Mackenzie

unread,
Feb 11, 2015, 7:44:22 AM2/11/15
to
It's something I'm sure I know, but I just can't find it anywhere.

In a bash script, I have a filename in, say, $f, which might be either
an absolute or a relative filename. I need an absolute name. So I need
a function/operator, foo, such that:

foo /home/acm/bar.sh => /home/acm/bar.sh
and
foo bar.sh => /home/acm/bar.sh
(assuming, of course, that PWD is /home/acm).

I could easily write this myself, but surely this already exists,
somewhere. What's it called, please?

--
Alan Mackenzie (Nuremberg, Germany).

Casper H.S. Dik

unread,
Feb 11, 2015, 8:07:04 AM2/11/15
to
realpath(1) which is part of GNU coreutils.

Casper

Kenny McCormack

unread,
Feb 11, 2015, 8:33:13 AM2/11/15
to
In article <54db53df$0$2885$e4fe...@news2.news.xs4all.nl>,
Note that that command often doesn't exist (read: Isn't installed by default)

On the system I'm typing on right now, "man realpath" gets me something in
section 3, not section 1. Thus the point of this post: If there isn't a
"realpath" command on your system, it's super-easy to whip one up yourself,
since all it is is a thin layer around the library call (the one documented
in section 3).

--
People who say they'll vote for someone else because Obama couldn't solve
all of Bush's messes are like people complaining that he couldn't cure cancer,
so they'll go and vote for cancer.

David W. Hodgins

unread,
Feb 11, 2015, 8:33:50 AM2/11/15
to
On Wed, 11 Feb 2015 07:44:19 -0500, Alan Mackenzie <a...@muc.de> wrote:

> In a bash script, I have a filename in, say, $f, which might be either
> an absolute or a relative filename. I need an absolute name. So I need
> a function/operator, foo, such that:
> I could easily write this myself, but surely this already exists,
> somewhere. What's it called, please?

$ realpath .xsession-errors
/home/dave/.xsession-errors

Regards, Dave Hodgins

--
Change nomail.afraid.org to ody.ca to reply by email.
(nomail.afraid.org has been set up specifically for
use in usenet. Feel free to use it yourself.)

Bit Twister

unread,
Feb 11, 2015, 9:27:16 AM2/11/15
to
On 11 Feb 2015 13:06:39 GMT, Casper H.S Dik wrote:
Alan Mackenzie <a...@muc.de> writes:

>> How do I convert a filename to absolute in bash

> realpath(1) which is part of GNU coreutils.

It would seem realpath is not a really easy tool to use in a diverse
environment. You know, where the user can modify their PATH or use an
alias, function,....

For instance, the simple case:

$ realpath uh
/home/bittwister/uh

$ ls /home/bittwister/uh
ls: cannot access /home/bittwister/uh: No such file or directory


So
$ type uh
uh is /local/bin/uh

Which is
$ ls -l /local/bin/uh
lrwxrwxrwx 1 root root 2 Jan 7 2011 /local/bin/uh -> ux

Alan Mackenzie

unread,
Feb 11, 2015, 9:34:19 AM2/11/15
to
Hello, Casper.
Perfect! Thanks for the answer.

I had thought there was a utility actually inside bash itself, but
evidently not. Now is the time to have a look at the coreutils
documentation to see if there's anything else handy there.

> Casper

Barry Margolin

unread,
Feb 11, 2015, 11:10:26 AM2/11/15
to
In article <slrnmdmpm1.i...@wb.home.test>,
realpath isn't for finding the location of programs. It just converts a
relative pathname to an absolute pathname. If your current directory is
/foo/bar/baz, "realpath uh" will return /foo/bar/baz/uh, regardless of
whether the file "uh" actually exists.

--
Barry Margolin, bar...@alum.mit.edu
Arlington, MA
*** PLEASE post questions in newsgroups, not directly to me ***

Kaz Kylheku

unread,
Feb 11, 2015, 11:10:45 AM2/11/15
to
On 2015-02-11, Alan Mackenzie <a...@muc.de> wrote:
> It's something I'm sure I know, but I just can't find it anywhere.
>
> In a bash script, I have a filename in, say, $f, which might be either
> an absolute or a relative filename. I need an absolute name. So I need
> a function/operator, foo, such that:
>
> foo /home/acm/bar.sh => /home/acm/bar.sh
> and
> foo bar.sh => /home/acm/bar.sh
> (assuming, of course, that PWD is /home/acm).

Another GNU Coreutils program which does this, besides realpath,
is the readlink command with the -f option. (Also look at the closely
related -e and -m).

Note that

readlink -f exists/nonexistent
readlink -f nonexistent
readlink -f ./nonexistent

will work, since -f allows the last path component to be nonexistent, whereas:

realpath exists/nonexistent
realpath nonexistent
realpath ./nonexistent

will fail. This could matter if the path is a proposed path of some
file that has not been created yet:

The strict behavior (all components must exist) can be obtained from readlink
using -e instead of -f.

A loose behavior (multiple components may not exist) can also be obtained
with -m. Example:

$ readlink -m a/b/c/../d/blah
/home/kaz/a/b/d/blah

realpath can produce an absolute path without expanding symlinks (realpath -s).
realink has no such feature.

If you want the current working directory as an absolute path with symlinks
expanded, you can use:

pwd -P

this one is POSIX standard.

Casper H.S. Dik

unread,
Feb 11, 2015, 11:44:04 AM2/11/15
to
Bit Twister <BitTw...@mouse-potato.com> writes:

>For instance, the simple case:

>$ realpath uh
>/home/bittwister/uh

Use "-e" which fail for non-exsting files

$ realpath /home/casper/nothing
/home/casper/nothing
$ realpath -e /home/casper/nothing
realpath: ‘/home/casper/nothing’: No such file or directory

There are some other tricks you can play with /proc; on several
system you can get the open file name using ls -l.

E.g., on Solaris

$ cd /etc; exec 3< motd
$ ls -l /proc/$$/path/3
lrwxrwxrwx 1 casper ir 0 Feb 11 17:40 /proc/20928/path/3 -> /etc/motd

Similar tricks can be used on Linux.

Casper

Hongyi Zhao

unread,
Jul 3, 2017, 9:19:05 AM7/3/17
to
On Wed, 11 Feb 2015 16:10:16 +0000, Kaz Kylheku wrote:

> Another GNU Coreutils program which does this, besides realpath,
> is the readlink command with the -f option. (Also look at the closely
> related -e and -m).

Are there any/some equivalent tool(s) / shell-builtins for the same
purpose if I don't use GNU-based OS?

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

Hongyi Zhao

unread,
Jul 3, 2017, 9:29:12 AM7/3/17
to
On Wed, 11 Feb 2015 16:10:16 +0000, Kaz Kylheku wrote:

Based on your above notes, if I want to obtain the absolute path of a
script, both the following two methods will do the job by putting the
following line in the script:

script_path="$(cd -P -- "$(dirname -- "$(readlink -f -- "$0")")" && pwd -
P)"

or


script_path="$(dirname -- "$(readlink -f -- "$0")")"

Which one is more preferable?

Casper H.S. Dik

unread,
Jul 3, 2017, 9:35:05 AM7/3/17
to
Hongyi Zhao <hongy...@gmail.com> writes:

>On Wed, 11 Feb 2015 16:10:16 +0000, Kaz Kylheku wrote:

>> Another GNU Coreutils program which does this, besides realpath,
>> is the readlink command with the -f option. (Also look at the closely
>> related -e and -m).

>Are there any/some equivalent tool(s) / shell-builtins for the same
>purpose if I don't use GNU-based OS?

That is pretty difficult; you could find the realpath of the directory
(cd $(dirname "$1"); pwd -P) but still does allow you to get expand the
final component.

What OSes do you have where the GNU tools are not installed (they may
not be installed by default in Solaris 11 but you can easily install them)

Casper

Kenny McCormack

unread,
Jul 3, 2017, 9:49:46 AM7/3/17
to
In article <ojdg82$vqf$1...@aspen.stu.neva.ru>,
Hongyi Zhao <hongy...@gmail.com> wrote:
>On Wed, 11 Feb 2015 16:10:16 +0000, Kaz Kylheku wrote:
>
>> Another GNU Coreutils program which does this, besides realpath,
>> is the readlink command with the -f option. (Also look at the closely
>> related -e and -m).
>
>Are there any/some equivalent tool(s) / shell-builtins for the same
>purpose if I don't use GNU-based OS?

As with all such things, this depends on what you're really trying to
accomplish and why. What are your actual constraints? Are you trying to do
this as an academic exercise or is there an actual need for it? Are you
the sort of person who prefers weird, complicated constructs that maintain
"POSIX conformance" as opposed to simple, obvious things that work, even if
they are not 100% compliant?

If you are using bash and have a current (4.4 or later) version fully,
correctly installed, then, yes, there is a "realpath" builtin, that can be
enabled using a command line like:

enable -f realpath realpath

Of course, if these conditions hold for you, then you're probably running
Linux (or something close to it), in which case, you're already there.

Note that if your system has "busybox" or if you can compile it yourself,
then you have another perfectly working, acceptable way to get "realpath"
functionality.

Or you could write it yourself - since it is basically a pass-thru to the
realpath(3) library call.

--
Modern Christian: Someone who can take time out from using Leviticus
to defend homophobia and Exodus to plaster the Ten Commandments on
every school and courthouse to claim that the Old Testament is merely
"ancient laws" that "only applies to Jews".

Hongyi Zhao

unread,
Jul 9, 2017, 4:50:37 AM7/9/17
to
On Wed, 11 Feb 2015 13:06:39 +0000, Casper H.S. Dik wrote:

> realpath(1) which is part of GNU coreutils.
>
> Casper

For transferability, I learned that `readlink -f` won't work on Mac, but
not sure about realpath. Instead of using realpath/readlink, we can
resort to python as follows:


# `readlink -f` won't work on Mac, this hack should work on all systems.
echo $(python -c "import os; print os.path.dirname(os.path.realpath
('$0'))")

Reggards

Kaz Kylheku

unread,
Jul 9, 2017, 11:10:46 AM7/9/17
to
On 2017-07-09, Hongyi Zhao <hongy...@gmail.com> wrote:
> On Wed, 11 Feb 2015 13:06:39 +0000, Casper H.S. Dik wrote:
>
>> realpath(1) which is part of GNU coreutils.
>>
>> Casper
>
> For transferability, I learned that `readlink -f` won't work on Mac, but
> not sure about realpath. Instead of using realpath/readlink, we can
> resort to python as follows:
>
>
> # `readlink -f` won't work on Mac, this hack should work on all systems.
> echo $(python -c "import os; print os.path.dirname(os.path.realpath
> ('$0'))")

Injecting a dependency on python being installed is a jaw-droppingly
stupid way to deal with some command not working on MacOS.

You might as well just demand that the Mac user have GNU Coreutils,
and then use realpath.

Kenny McCormack

unread,
Jul 9, 2017, 1:29:08 PM7/9/17
to
In article <201707090...@kylheku.com>,
Kaz Kylheku <686-67...@kylheku.com> wrote:
>On 2017-07-09, Hongyi Zhao <hongy...@gmail.com> wrote:
>> On Wed, 11 Feb 2015 13:06:39 +0000, Casper H.S. Dik wrote:
>>
>>> realpath(1) which is part of GNU coreutils.
...
>> # `readlink -f` won't work on Mac, this hack should work on all systems.
>> # I.e., "all" systems that have Python installed.

>Injecting a dependency on python being installed is a jaw-droppingly
>stupid way to deal with some command not working on MacOS.

Well, that was certainly my first reaction as well, but, FWIW, I think
Macs (i.e., OSX) do come with Python pre-installed.

For a person of Hongyi's obviously limited skills and scope of problem, it
seems reasonable to assume that if it works on his system (which it will),
then the problem is solved.

>You might as well just demand that the Mac user have GNU Coreutils,
>and then use realpath.

Or, even easier, write your own - given that, as I said earlier, it's just
a very thin wrapper around realpath(3). A few lines of C would do it.

FWIW, I wrote one in AWK, that I used for a long time until I figured out
that it was available as a bash builtin. Of course, this was my own,
customizer version of GAWK that has the ability to call system library
functions from GAWK source. Again, in the FWIW, I think you could do it in
stock Perl (I don't do Perl so can't say for sure), since I think Perl
gives direct access to system library functions (without the need for a
local hack to the source code).

--
The randomly chosen signature file that would have appeared here is more than 4
lines long. As such, it violates one or more Usenet RFCs. In order to remain
in compliance with said RFCs, the actual sig can be found at the following URL:
http://user.xmission.com/~gazelle/Sigs/Pearls

John McCue

unread,
Jul 13, 2017, 2:18:38 PM7/13/17
to
Hongyi Zhao <hongy...@gmail.com> wrote:
> On Wed, 11 Feb 2015 16:10:16 +0000, Kaz Kylheku wrote:
>
<snip>
>
> Are there any/some equivalent tool(s) / shell-builtins for the same
> purpose if I don't use GNU-based OS?

This works on AIX using /bin/sh (which is really ksh
on the systems I have acces to):

#----------------------------
fname=P/x.txt

(
cd `dirname $fname`
echo `pwd`/`basename $fname`
) | read fullfile

echo $fullfile
#----------------------------

John

PS: really hoping this is not homework :)

Kaz Kylheku

unread,
Jul 13, 2017, 3:22:37 PM7/13/17
to
Even if it is, nobody is going to get marks in July 2017 for homework
they were assigned in February 2015.

John McCue

unread,
Jul 15, 2017, 2:31:42 PM7/15/17
to
I did not know this was from 2015, if I did I would
have ignored it. I do not like responding to necro
threads :)

John
0 new messages