Python 删除路径中的第一个文件夹

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26724275/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 00:56:08  来源:igfitidea点击:

Removing the first folder in a path

pythonpath

提问by meto

I have a path which looks like

我有一条看起来像的路径

/First/Second/Third/Fourth/Fifth

and I would like to remove the Firstfrom it, thus obtaining

我想从中删除First,从而获得

Second/Third/Fourth/Fifth

The only idea I could come up with is to use recursively os.path.splitbut this does not seem optimal. Is there a better solution?

我能想到的唯一想法是递归使用,os.path.split但这似乎不是最佳选择。有更好的解决方案吗?

采纳答案by abarnert

There really is nothing in the os.pathmodule to do this. Every so often, someone suggests creating a splitallfunction that returns a list (or iterator) of all of the components, but it never gained enough traction.

os.path模块中确实没有任何东西可以做到这一点。每隔一段时间,有人建议创建一个splitall函数来返回所有组件的列表(或迭代器),但它从未获得足够的吸引力。

Partly this is because every time anyone ever suggested adding new functionality to os.path, it re-ignited the long-standing dissatisfaction with the general design of the library, leading to someone proposing a new, more OO-like, API for paths to deprecated the os, clunky API. In 3.4, that finally happened, with pathlib. And it's already got functionality that wasn't in os.path. So:

这部分是因为每次有人曾经建议增加新的功能os.path,它重新点燃了与图书馆的总体设计已久的不满,导致有人提出了一个新的,更OO状,对路径的API弃用操作系统,笨重的API。在 3.4 中,这终于发生了,使用pathlib. 它已经具备了os.path. 所以:

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

Or… are you sure you really want to remove the first component, rather than do this?

或者……您确定真的要删除第一个组件,而不是这样做吗?

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

If you need to do this in 2.6-2.7 or 3.2-3.3, there's a backport of pathlib.

如果你需要做这在2.6-2.7或3.2-3.3,有一个的反向移植pathlib

Of course, you can use string manipulation, as long as you're careful to normalize the path and use os.path.sep, and to make sure you handle the fiddly details with non-absolute paths or with systems with drive letters, and…

当然,您可以使用字符串操作,只要您小心地规范化路径并使用os.path.sep,并确保您使用非绝对路径或带有驱动器号的系统处理繁琐的细节,并且......

Or you can just wrap up your recursive os.path.split. What exactly is "non-optimal" about it, once you wrap it up? It may be a bit slower, but we're talking nanoseconds here, many orders of magnitude faster than even calling staton a file. It will have recursion-depth problems if you have a filesystem that's 1000 directories deep, but have you ever seen one? (If so, you can always turn it into a loop…) It takes a few minutes to wrap it up and write good unit tests, but that's something you just do once and never worry about again. So, honestly, if you don't want to use pathlib, that's what I'd do.

或者你可以结束你的递归os.path.split。一旦你把它包起来,究竟什么是“非最佳”?它可能会慢一点,但我们在这里谈论的是纳秒,比调用stat文件快很多数量级。如果您有一个深度为 1000 个目录的文件系统,它将存在递归深度问题,但是您见过吗?(如果是这样,你总是可以把它变成一个循环......)把它包装起来并编写好的单元测试需要几分钟,但这是你只做一次就不会再担心的事情。所以,老实说,如果你不想使用pathlib,那就是我会做的。

回答by Hackaholic

A simple approach

一个简单的方法

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

output:

输出:

Second/Third/Fourth/Fifth

In this above code i have split the string. then joined leaving 1st element

在上面的代码中,我拆分了字符串。然后加入离开第一个元素

Using itertools.dropwhile:

使用itertools.dropwhile

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

回答by amyrit

A bit like another answer, taking advantage of os.path :

有点像另一个答案,利用 os.path :

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

... assuming your string starts with a separator.

...假设您的字符串以分隔符开头。

回答by tupan

I was looking if there was a native way to do it, but it seems it doesn't.

我正在寻找是否有本地方法可以做到这一点,但似乎没有。

I know this topic is old, but this is what I did to get me to the best solution: There was two basically two approaches: using split() and using len(). Both had to use slicing.

我知道这个话题很老,但这是我为找到最佳解决方案所做的:基本上有两种方法:使用 split() 和使用 len()。两者都必须使用切片。

1) Using split()

1) 使用 split()

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))

Result: --- 0.420122861862 seconds ---

结果:--- 0.420122861862 秒---

*Removing the char "/" in the line new_path = "/" + "/".... didn't improve the performance too much.

*删除 new_path = "/" + "/" .... 行中的字符 "/" 并没有太大提高性能。

2) Using len(). This method will only work if you provide the folder if you would like to remove

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))

Result: --- 0.199596166611 seconds ---

结果:--- 0.199596166611 秒---

*Even with that "if" to check if the path starts with the file name, it was twice as fast as the first method.

*即使使用“if”来检查路径是否以文件名开头,它的速度也是第一种方法的两倍。

In summary: each method has a pro and con. If you are absolutely sure about the folder you want to remove use method two, otherwise I recommend to use method 1 which people here have mentioned previously.

总之:每种方法都有优点和缺点。如果您绝对确定要删除的文件夹使用方法二,否则我建议使用这里人之前提到的方法一。

回答by Den-Jason

You can try:

你可以试试:

os.path.relpath(your_path, '/First')