I'm not sure if these paths are duplicates. Given the relative path, how do I determine absolute path using a shell script?
Example:
relative path: /x/y/../../a/b/z/../c/d
absolute path: /a/b/c/d
I'm not sure if these paths are duplicates. Given the relative path, how do I determine absolute path using a shell script?
Example:
relative path: /x/y/../../a/b/z/../c/d
absolute path: /a/b/c/d
Take a look at 'realpath'.
May be this helps:
The most reliable method I've come across in unix is
readlink -f
:A couple caveats:
readlink
will give a blank result if you reference a non-existant directory. If you want to support non-existant paths, usereadlink -m
instead. Unfortunately this option doesn't exist on versions of readlink released before ~2005.From this source comes:
You can also do a Perl one-liner, e.g. using
Cwd::abs_path
Since I've run into this many times over the years, and this time around I needed a pure bash portable version that I could use on OSX and linux, I went ahead and wrote one:
The living version lives here:
https://github.com/keen99/shell-functions/tree/master/resolve_path
but for the sake of SO, here's the current version (I feel it's well tested..but I'm open to feedback!)
Might not be difficult to make it work for plain bourne shell (sh), but I didn't try...I like $FUNCNAME too much. :)
here's a classic example, thanks to brew:
use this function and it will return the -real- path:
Using bash
${relative_file%/*}
is same result asdirname "$relative_file"
${relative_file##*/}
is same result asbasename "$relative_file"
Caveats: Does not resolve symbolic links (i.e. does not canonicalize path ) => May not differentiate all duplicates if you use symbolic links.
Using
realpath
Command
realpath
does the job. An alternative is to usereadlink -e
(orreadlink -f
). Howeverrealpath
is not often installed by default. If you cannot be surerealpath
orreadlink
is present, you can substitute it using perl (see below).Using perl
Steven Kramer proposes a shell alias if
realpath
is not available in your system:or if you prefer using directly perl:
This one-line perl command uses
Cwd::realpath
. There are in fact three perl functions. They take a single argument and return the absolute pathname. Below details are from documentation Perl5 > Core modules > Cwd.abs_path()
uses the same algorithm asgetcwd()
. Symbolic links and relative-path components (.
and..
) are resolved to return the canonical pathname, just likerealpath
.realpath()
is a synonym forabs_path()
fast_abs_path()
is a more dangerous, but potentially faster version ofabs_path()
These functions are exported only on request => therefore use
Cwd
to avoid the "Undefined subroutine" error as pointed out by arielf. If you want to import all these three functions, you can use a singleuse Cwd
line: