2013-06-22 29 views
0

這是一個微妙的問題,我知道,但我希望你能忍受我一會兒。展開一個相對路徑,但不遵循Python中路徑中的任何符號鏈接

假設/tmp/dir是符號鏈接/home/user/some/dir。假設你的當前工作目錄是/tmp/dir

即使擴大像.似乎並不可能,因爲os.getcwd()回報/home/user/some/dir代替/tmp/dir,這是什麼pwd命令返回。相對目錄,也可以../dir/../dir/subdir.././././dir/foo

所以我的問題:是否有做了相對路徑的路徑擴展,但並不意味着可以在相對路徑存在的符號鏈接任何可靠的功能。例如,在../dir/../dir/subdir的情況下,我想獲得/tmp/dir/subdir而不是/home/user/some/dir/subdir

只是爲了避免得到我不想要的東西,答案不是os.path.abspathos.path.realpath,os.path.expanduseros.path.relpath

+0

你確定,你沒有通過'os.path.realpath(os.path。expanduser('../ dir /../ dir/subdir'))' – podshumok

+0

@podshumok然後你會得到'/ home/user/some/dir/subdir',這就是我不想得到的。 – OTZ

+1

奇怪。如果我設置了這些確切的條件,即使我在'/ tmp/dir'中,'os.getcwd()'實際上也會返回'/ home/user/some/dir'。不知道它是否重要,但可能值得指定使用哪個Python版本以防萬一它改變。 – Aya

回答

1

好像you're not the first注意到的chdir(2)這種奇怪的行爲。

沒有什麼關於它在Linux手冊頁,但a similar page說...

int chdir(const char *path);

[...]

CHDIR()功能,使目錄中名爲通過路徑新的 當前目錄。如果路徑的最後一個組件是是一個符號鏈接,則 chdir()解析了符號鏈接的內容。如果chdir()函數失敗,則當前目錄不變。

...雖然沒有解釋爲什麼它解決了符號鏈接。

因此,即使您的shell聲明瞭其他方法,您在技術上也無法擁有當前的工作目錄/tmp/dir

不過,你可以利用一個事實,即外殼的內置命令cd設置環境變量PWD到您輸入的值,這樣你就可以做到這一點...

$ cd /tmp/dir 
$ python 
>>> import os 
>>> os.getcwd() 
'/home/user/some/dir' 
>>> os.environ['PWD'] 
'/tmp/dir' 
>>> os.path.normpath(os.path.join(os.environ['PWD'], '../dir/../dir/subdir')) 
'/tmp/dir/subdir' 

...雖然它在進程不是從shell啓動的情況下可能會失敗。

+0

非常感謝您徹底調查此問題。我確實嘗試過'os.environ ['PWD']',但並沒有像你那樣走得太遠。 'os.path.normpath'規範化確實工作得更好,在這種情況下確實可能是最好的選擇。沒有時間查看'pwd'命令的源代碼;我懷疑它在內部做了什麼可能不完全可以實現。再次感謝,綾! – OTZ

+0

@OTZ內置''pwd' shell幾乎只是'echo $ PWD',而'/ bin/pwd'幾乎就是'print os.getcwd()'。 – Aya

0

不確定這就是您要找的內容,但是...您可以編寫一個函數,從相對路徑和當前工作目錄生成「邏輯」完整路徑,然後檢查生成的路徑是否真的存在於系統中。這個函數可能看起來像:

import os 

def absolute_path(path): 
    wd = os.getcwd() 
    full = os.path.join(wd, path) 

    parts = full.split(os.sep) 
    kept = [] 
    skip = 0 
    for part in reversed(parts): 
     if part == '..': 
      skip += 1 
     elif skip == 0: 
      kept.insert(0, part) 
     else: 
      skip -= 1 
    return os.sep + os.path.join(*kept)