Bash's cd
command has a couple of interesting but little-used options, -P
and -L
.
cd [-L|[-P [-e]] [-@]] [dir]
... The -P option causes cd to use the physical directory
structure by resolving symbolic links while traversing dir and
before processing instances of .. in dir (see also the -P option
to the set builtin command); the -L option forces symbolic links
to be followed by resolving the link after processing instances
of .. in dir. ...
So ... if you're looking for the physical location in the filesystem of your current working directory, you could use something like this:
realwd="$(cd -P .; pwd)"
In your comments, you mentioned that you're looking for the parent directory of the directory containing a file -- so, if a path is /foo/bar/baz/filename
, you'd be looking for /foo/bar
.
To get this, I would suggest a combination of cd -P
and parameter expansion. Since you know that the /
character can never exist as part of a filename, the following might work for you:
grandparent() {
local realdir="$(cd -P "${1%/*}"; pwd)"
echo "${realdir%/*}"
}
This works by using cd -P
to "get" the physical location of the file, then parameter expansion to strip off the last item in the path.
$ mkdir -p one/two/three
$ touch one/two/three/foo
$ ln -s one/two/three bar
$ ls -l bar
lrwxr-xr-x 1 ghoti wheel 13 Nov 19 23:05 bar -> one/two/three
$ grandparent bar/foo
/usr/home/ghoti/tmp6/one/two