2014-11-03 73 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。