2014-11-03 98 views
15

我有一個看起來像刪除第一個文件夾的路徑

/First/Second/Third/Fourth/Fifth 

,我想刪除它的First,從而獲得

Second/Third/Fourth/Fifth 

唯一的想法我能來的路徑與遞歸地使用os.path.split,但這似乎並不理想。有更好的解決方案嗎?

回答

13

模塊os.path確實沒有這樣做。每隔一段時間,有人建議創建一個返回所有組件的列表(或迭代器)的函數,但它從來沒有獲得足夠的吸引力。部分原因是每次有人建議添加新功能到os.path時,它重新點燃了對圖書館常規設計的長期不滿,導致有人提出了一種新的更類似OO的API不贊成使用os和笨重API的路徑。在3.4中,終於發生了,與pathlib。它的功能已經不在os.path。所以:

>>> p = pathlib.Path('/First/Second/Third/Fourth/Fifth') 
>>> p.parts[2:] 
('Third', 'Fourth', 'Fifth') 
>>> pathlib.Path(*p.parts[2:]) 
PosixPath('Second/Third/Fourth/Fifth') 

或者......你確定你真的想刪除第一個組件,而不是這樣做嗎?

>>> p.relative_to(*p.parts[:2]) 
PosixPath('Second/Third/Fourth/Fifth') 

如果你需要這樣做在2.6-2.7或3.2-3.3,有一個backport of pathlib

當然,只要您仔細規劃路徑並使用os.path.sep,並確保您使用非絕對路徑或帶有驅動器號的系統處理煩瑣的細節,您可以使用字符串操作,以及...

或者你可以只包裝你的遞歸os.path.split。一旦你把它包起來,究竟是什麼「非最優」呢?它可能會慢一點,但我們在這裏說的是納秒,比在一個文件上調用stat要快很多個數量級。如果你的文件系統有1000個目錄,但是你有沒有看過一個文件系統,那麼它會產生遞歸深度問題? (如果是這樣,你總是可以把它變成一個循環......)它需要幾分鐘才能完成並編寫好的單元測試,但這只是你做了一次而且再也不用擔心。所以,說實話,如果你不想使用pathlib,那就是我要做的。

+0

'pathlib' dosent帶有python,需要安裝它 – Hackaholic 2014-11-03 22:33:37

+0

性能明智,你是完全正確的:我們正在談論納秒;更多的是我試圖學習最好的方式/其他方式 – meto 2014-11-03 22:48:15

+0

@Hackaholic:正如答案詳細解釋的那樣,'pathlib'附帶Python 3.4+,並且您可以安裝2.6-2.7或3.2-3.3的backport 。 – abarnert 2014-11-03 22:52:19

4

一種簡單的方法

a = '/First/Second/Third/Fourth/Fifth' 
"/".join(a.strip("/").split('/')[1:]) 

輸出:

Second/Third/Fourth/Fifth 

在該上述代碼我已分割字符串。再加入剩下1元

使用itertools.dropwhile

>>> a = '/First/Second/Third/Fourth/Fifth' 
>>> "".join(list(itertools.dropwhile(str.isalnum, a[1:]))[1:]) 
'Second/Third/Fourth/Fifth' 
+0

起初我以爲這不適用於以路徑分隔符開頭的路徑,因爲您似乎大肆剝離字符串中的第一個字符,但經過進一步檢查,如果您剛剛刪除第一個分段,第一個字符會起什麼作用。 +1,但也許在答覆中提到了這一點(或者可能是你幫助過的人發表的評論) – iLoveTux 2015-10-12 19:06:01

+0

@iLoveTux使它更有效 – Hackaholic 2015-10-13 10:54:19

8

像另一個答案了一下,以os.path中的優勢:

os.path.join(*(x.split(os.path.sep)[2:])) 

...假設你的字符串分隔開始。

+1

你能否在這裏解釋一下關於「*」的用法? – Luke 2017-02-24 17:14:38

+0

@Luke該*用於將'(x.split(os.path.sep)[2:])生成的集合視爲'* args'關鍵字。但是,這將不起作用,因爲參數列表將完全爲空,所以路徑太短 – asdf 2017-10-13 03:07:35

1

我一直在尋找是否有原生的方式來做到這一點,但它似乎沒有。

我知道這個話題是舊的,但這是我爲了讓我找到最好的解決方案: 有兩種基本上兩種方法:使用split()和使用len()。兩者都必須使用切片。

1)使用拆分()

import time 

start_time = time.time() 

path = "/folder1/folder2/folder3/file.zip" 
for i in xrange(500000): 
    new_path = "/" + "/".join(path.split("/")[2:]) 

print("--- %s seconds ---" % (time.time() - start_time)) 

結果:---0.420122861862秒---

*卸下炭 「/」 在線new_path = 「/」 +「 /「....沒有提高太多的表現。

2)使用len()。如果您提供的文件夾這種方法只會工作,如果你想刪除

import time 

start_time = time.time() 

path = "/folder1/folder2/folder3/file.zip" 
folder = "/folder1" 
for i in xrange(500000): 
    if path.startswith(folder): 
     a = path[len(folder):] 

print("--- %s seconds ---" % (time.time() - start_time)) 

結果:---0.199596166611秒---

*即使「如果」檢查如果路徑以文件名開頭,則是第一種方法的兩倍。

總結:每種方法都有一個pro和con。如果你完全確定要刪除的文件夾使用方法二,否則我建議使用前面提到過的方法1。