You can always create a function to be used with the +
glob qualifier:
$ zmodload zsh/stat
$ resolve() { [[ -L $REPLY ]] && stat -A REPLY +link -- ${1-$REPLY}; }
$ print -r - a(+resolve)
b
$ print -r - a(+resolve:a)
/home/stephane/b (though see caveat below)
Note that if you do a(+resolve+resolve)
, the second resolve
will still be called on the original filename (a
), not on the result of the first resolve
(b
). You could however do:
$ print -r - a(e['resolve && resolve'])
c
to chain the two resolve
s. However (and the caveat also applies to the usage of :a
above), although it will work for this particular example, that's not a valid thing to do in the general case, as targets of symlinks, when relative paths, are relative to the parent of the symlink, not the current working directory, so if dir/link
points to foo
, that's the dir/foo
file, not foo
, so it's only valid when resolving symlinks in the current working directory.
That would stop being a problem though if we change our resolve
so it computes a full path of the target of the symlink:
resolve() {
local target
[[ -L $REPLY ]] &&
stat -A target +link -- ${1-$REPLY} &&
case $target in
(/*) REPLY=$target;;
(*) REPLY=${REPLY:h:a}/$target;;
esac
}
bash
has no glob qualifier, nor any interface to readlink()
(like zsh
's stat
builtin), but on some systems, you'll find a readlink
command:
$ readlink a
b