Converting relative path to absolute path without symbolic link
You can use the readlink
utility, with the -f
option:
-f, --canonicalize
canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist
Some distributions, for example those that use GNU coreutils and FreeBSD, also come with a realpath(1)
utility that basically just calls realpath(3)
and does pretty much the same thing.
Portably, the PWD
variable is set by the shell to one absolute location of the current directory. Any component of that path may be a symbolic link.
case $f in
/*) absolute=$f;;
*) absolute=$PWD/$f;;
esac
If you want to eliminate .
and ..
as well, change to the directory containing the file and obtain $PWD
there:
if [ -d "$f" ]; then f=$f/.; fi
absolute=$(cd "$(dirname -- "$f")"; printf %s. "$PWD")
absolute=${absolute%?}
absolute=$absolute/${f##*/}
There's no portable way to follow symbolic links. If you have a path to a directory, then on most unices $(cd -- "$dir" && pwd -P 2>/dev/null || pwd)
provides a path that doesn't use symbolic links, because shells that track symbolic links tend to implement pwd -P
(“P” for “physical”).
Some unices provide a utility to print the “physical” path to a file.
- Reasonably recent Linux systems (with GNU coreutils or BusyBox) have
readlink -f
, as do FreeBSD ≥8.3, NetBSD ≥4.0, and OpenBSD as far back as 2.2. - FreeBSD ≥4.3 has
realpath
(it's also present on some Linux systems, and it's in BusyBox). If Perl is available, you can use the
Cwd
module.perl -MCwd -e 'print Cwd::realpath($ARGV[0])' path/to/file
Is pwd
fit for your needs? It gives the absolute path of current directory. Or maybe what you want is realpath().