On Tue, Aug 9, 2011 at 2:14 PM, Bob Proulx <[email protected]> wrote:
> Jon Seymour wrote:
>> I always use sed for this purpose, so:
>>
>> $(cd "$dir"; ls -l "$base" | sed "s/.*->//")
>>
>> But, with pathological linking structures, this isn't quite enough -
>> particularly if the target of the link itself contains paths, some of
>> which may contain links :-)
>
> Agreed! Symlinks with arbitrary data, such as holding small shopping
> lists in the target value, are so much fun. I am more concerned that
> arbitrary data such as "->" might exist in there more so than
> whitespace. That is why I usually don't use a pattern expression.
> But I agree it is another way to go. But it is easier to say
> whitespace is bad in filenames than to say whitespace is bad and oh
> yes you can't have "->" in there either. :-)
>
Ok, I think this does it...
readlink_f()
{
local path="$1"
test -z "$path" && echo "usage: readlink_f path" 1>&2 && exit 1;
local dir
if test -L "$path"
then
local link=$(ls -l "$path" | sed "s/.*-> //")
if test "$link" = "${link#/}"
then
# relative link
dir="$(dirname "$path")"
readlink_f "${dir%/}/$link"
else
# absolute link
readlink_f "$link"
fi
elif test -d "$path"
then
(cd "$path"; pwd -P) # normalize it
else
dir="$(cd $(dirname "$path"); pwd -P)"
base="$(basename "$path")"
echo "${dir%/}/${base}"
fi
}