Suppose I create a symbolic link "file2" to a file "file1" two directories above the current location (e.g., "ln -s ../../file1 file2". But now suppose that "file1" is also a symbolic link to a file "file0" two directories down from its location (say its relative path is dir1/dir2/file0").
I'd prefer if the "file1" symbolic link contains a relative URL going to file0 "../../dir1/dir2/file0" rather than just "../../file1". That latter only indirectly points to the file.
What's a good way of doing this?
I could hack together something with readlink. But I'm still hoping there's an "better" way that I'm not considering or have overlooked.
This will recursively test a file and retrieve a complete relative path, then remove unnecessary "./" and "foo/../"
#!/bin/bash
linkfile="$1"
while test -L "$linkfile" ; do
linkfile="$(dirname ${linkfile})/$(readlink ${linkfile})"
done
perl -e '$x=shift; while ($x =~ s#//+#/#g) {} ; while ($x =~ s#/\./#/#g) {} ; while ($x =~ s#/([^\.]|[^\.][^/]+?|\.[^\.]+?)/\.\./#/#g) {} ; while ($x =~ s#^([^\.]|[^\.][^/]+?|\.[^\.]+?)/\.\./#/#g) {} ; $x =~ s#^\./##; print "$x\n";' "$linkfile"
If you save that as "canonical.bash", then you use it
$ ln -s `canonical.bash foo` bar
The regex won't reduce a few cases like "/..x/../" and "../foo/" (if foo/ is in your $PWD), but should be otherwise sturdy.