2011-07-23 477 views
1

假設我在文件「file1」上創建了一個符號鏈接「file2」,位於當前位置上方的兩個目錄(例如「ln -s ../../file1 file2」 。但現在假設「file1」也是一個文件「file0」從它的位置向下兩個目錄的符號鏈接(假設它的相對路徑是dir1/dir2/file0)符號鏈接到符號鏈接...部分規範化

我寧願如果「 file1「的符號鏈接包含一個相對URL,它將轉到file0」../../dir1/dir2/file0「,而不僅僅是」../../file1「。後者只是間接指向該文件。

這樣做的好方法是什麼?

我可以與readlink一起破解一些東西。但我仍然希望有一種我不考慮或忽視的「更好」方式。

+0

應該是'canonization':-) – TMS

+0

這個問題與許多使用搜索關鍵詞「絕對」,「相對」和「路徑」相關,如[BASH:將絕對路徑轉換爲給定當前目錄的相對路徑] (http://stackoverflow.com/questions/2564634/bash-convert-absolute-path-into-relative-path-given-a-current-directory)。不幸的是,我還沒有答案可以接受。 –

+0

你的評論讓我記得...看到其他答案。 – TMS

回答

1

這將遞歸測試文件和檢索

#!/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" 

如果保存完整的相對路徑,然後刪除不必要的「./」和‘富/../’,作爲‘canonical.bash’那你就用它

$ ln -s `canonical.bash foo` bar 

正則表達式不會降低少數情況下,像「/..x/../」和「../foo/」(如果富/在你的$ PWD)但應該是堅固的。

+0

這個腳本似乎回答了我問的問題。然而,它並沒有在所有情況下傳遞最短的相對路徑。這個例子失敗了:讓「/ home/user/dir1」包含一個包含「file.txt」的目錄「dir2」。假設「link1」也存在並指向「dir2/file.txt」和「link2」,並且指向「../dir1/../dir1/link1」。該腳本按預期方式返回「../dir1/dir2/file.txt」而不是「dir2/file.txt」。 –

+0

我不滿足於不得不求助於perl。沒有它的解決方案會更優雅。 –

+0

正如你在另一個問題中所看到的那樣,將相對路徑轉化爲規範路徑具有挑戰性。我扔了一個快速的正則表達式來處理它,並有Perl模塊可以更好地處理它,但我不知道有一個標準的shell命令來完成它。 – brightlancer

0

不,這是非常具體的,我認爲你將不得不使用readlink並自己實現它。

0

現在我記得了!我看到大約15年前實現這個功能的工具!見man symlinks(1)symlinks -c。如果這不是你想要的,我想你的需求是非常明確的,你必須自己編寫代碼......(如果我記得很清楚,我還爲處理我的磁盤上的符號鏈接做了一些實用工具...)。 PERL是一個偉大的語言。

+0

這是一個有趣的工具(在Ubuntu 10.04版本中),但它並沒有做我想要完成的工作。我在StackOverflow發現了一些bash腳本,它們可以解決這個問題,但沒有什麼能完全令人滿意。我現在考慮投入時間寫我自己的。希望不必這樣做。如果我寫一些我感到自豪的作品,我會發布。 –