Suppose I create a symbolic link "file2" to a file "file1" two directories above the current location (e.g., "ln -s ../../file1 file开发者_如何学编程2". 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.
No, this is so specific that I think you'll have to use readlink and implement it yourself.
Now I remember!! I saw a utility which accomplishes this some 15 years ago! See man symlinks(1)
! symlinks -c
. If this is not what you want, I suppose your needs are so specific you would have to code it yourself... (if I remember well, I also made some utility for handling symlinks on my disk...). PERL is a great language for that.
精彩评论