我有一个表示dos路径的字符串变量,例如:
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
我想将此字符串拆分为:
[ "d", "stuff", "morestuff", "furtherdown", "THEFILE.txt" ]
我尝试过使用split()
和replace()
,但他们要么只处理第一个反斜杠,要么在字符串中插入十六进制数字。
我需要以某种方式将此字符串变量转换为原始字符串,以便我可以解析它。
最好的方法是什么?
我还应该补充一点var
的内容,即我尝试解析的路径,实际上是命令行查询的返回值。这不是我自己生成的路径数据。它存储在一个文件中,命令行工具不会逃避反斜杠。
答案 0 :(得分:220)
我愿意
import os
path = os.path.normpath(path)
path.split(os.sep)
首先将路径字符串规范化为OS的正确字符串。然后os.sep
必须安全地用作字符串函数拆分中的分隔符。
答案 1 :(得分:139)
我一直被人们写下自己的路径摆弄功能并弄错了。空格,斜线,反斜线,冒号 - 混淆的可能性并非无穷无尽,但无论如何都很容易犯错误。所以我是使用os.path
的坚持者,并在此基础上推荐它。
(然而,走向美德的道路并不是最容易采取的道路,很多人在发现这种道路时,很容易直接走向诅咒。他们直到有一天一切都会崩溃,他们才会意识到 - 或者,更有可能的是,其他人 - 必须解决为什么一切都出错了,事实证明有人制作了混合斜杠和反斜杠的文件名 - 而且有人建议答案是“不要这样做”不要成为这些人中的任何一个。除了混合斜杠和反斜杠的人之外 - 如果你愿意,你可以成为他们。)
您可以像这样获取驱动器和路径+文件:
drive, path_and_file = os.path.splitdrive(path)
获取路径和文件:
path, file = os.path.split(path_and_file)
获取单个文件夹名称并不是特别方便,但它是一种诚实的中等不适,增加了以后找到实际效果良好的乐趣:
folders = []
while 1:
path, folder = os.path.split(path)
if folder != "":
folders.append(folder)
else:
if path != "":
folders.append(path)
break
folders.reverse()
(如果路径最初是绝对路径,则会在"\"
的开头弹出folders
。如果您不想要,可能会丢失一些代码。)
答案 2 :(得分:72)
你可以简单地使用最Pythonic方法(恕我直言):
import os
your_path = r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
path_list = your_path.split(os.sep)
print path_list
哪个会给你:
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
此处的线索是使用os.sep
代替'\\'
或'/'
,因为这会使系统无关。
要从驱动器号中删除冒号(虽然我没有看到您为什么要这样做的原因),但您可以写:
path_list[0] = path_list[0][0]
答案 3 :(得分:41)
在Python> = 3.4中,这变得更加简单。您现在可以使用pathlib.Path.parts
获取路径的所有部分。
示例:
>>> from pathlib import Path
>>> Path('C:/path/to/file.txt').parts
('C:\\', 'path', 'to', 'file.txt')
>>> Path(r'C:\path\to\file.txt').parts
('C:\\', 'path', 'to', 'file.txt')
在Windows 3的Windows安装中,这将假设您正在使用Windows路径,而在* nix上,它将假定您正在使用posix路径。这通常是您想要的,但如果不是,您可以根据需要使用课程pathlib.PurePosixPath
或pathlib.PureWindowsPath
:
>>> from pathlib import PurePosixPath, PureWindowsPath
>>> PurePosixPath('/path/to/file.txt').parts
('/', 'path', 'to', 'file.txt')
>>> PureWindowsPath(r'C:\path\to\file.txt').parts
('C:\\', 'path', 'to', 'file.txt')
>>> PureWindowsPath(r'\\host\share\path\to\file.txt').parts
('\\\\host\\share\\', 'path', 'to', 'file.txt')
编辑: 还有一个可以使用python 2的后端:pathlib2
答案 4 :(得分:11)
这里的问题首先从你如何创建字符串开始。
a = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
通过这种方式,Python正在尝试这些特例:\s
,\m
,\f
和\T
。在您的情况下,\f
被视为换页(0x0C),而其他反斜杠被正确处理。你需要做的是其中之一:
b = "d:\\stuff\\morestuff\\furtherdown\\THEFILE.txt" # doubled backslashes
c = r"d:\stuff\morestuff\furtherdown\THEFILE.txt" # raw string, no doubling necessary
然后,一旦你拆开其中任何一个,你就会得到你想要的结果。
答案 5 :(得分:9)
有关更简洁的解决方案,请考虑以下事项:
def split_path(p):
a,b = os.path.split(p)
return (split_path(a) if len(a) and len(b) else []) + [b]
答案 6 :(得分:4)
我实际上无法真正回答这个问题(因为我来到这里希望自己找到一个),但对我来说,不同方法的数量以及所提到的所有警告都是Python的os.path模块的最可靠指标迫切需要这个作为内置功能。</ p>
答案 7 :(得分:3)
它对我有用:
>>> a=r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
>>> a.split("\\")
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
当然,您可能还需要从第一个组件中删除冒号,但保留它可以重新组装路径。
r
修饰符将字符串文字标记为“原始”;注意嵌入式反斜杠不会加倍。
答案 8 :(得分:1)
假设您有一个包含内容的文件filedata.txt
:
d:\stuff\morestuff\furtherdown\THEFILE.txt
d:\otherstuff\something\otherfile.txt
您可以阅读和拆分文件路径:
>>> for i in open("filedata.txt").readlines():
... print i.strip().split("\\")
...
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
['d:', 'otherstuff', 'something', 'otherfile.txt']
答案 9 :(得分:1)
关于约mypath.split("\\")
的内容最好表达为mypath.split(os.pathsep)
。 pathsep
是您的特定平台的路径分隔符(例如,Windows的\
,Unix的/
等),Python构建知道要使用哪个。如果您使用pathsep
,那么您的代码将与平台无关。
答案 10 :(得分:1)
re.split()可以比string.split()
多一点import re
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
re.split( r'[\\/]', var )
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
如果您还想支持Linux和Mac路径,只需添加过滤器(无,结果),这样就会从split()中删除不需要的'',因为它们的路径以'/'或'//'开头。例如'// mount / ...'或'/ var / tmp /'
import re
var = "/var/stuff/morestuff/furtherdown/THEFILE.txt"
result = re.split( r'[\\/]', var )
filter( None, result )
['var', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
答案 11 :(得分:1)
功能方式,使用生成器。
def split(path):
(drive, head) = os.path.splitdrive(path)
while (head != os.sep):
(head, tail) = os.path.split(head)
yield tail
行动中:
>>> print([x for x in split(os.path.normpath('/path/to/filename'))])
['filename', 'to', 'path']
答案 12 :(得分:1)
您可以递归os.path.split
字符串
import os
def parts(path):
p,f = os.path.split(path)
return parts(p) + [f] if f else [p]
针对某些路径字符串对此进行测试,并使用os.path.join
>>> for path in [
... r'd:\stuff\morestuff\furtherdown\THEFILE.txt',
... '/path/to/file.txt',
... 'relative/path/to/file.txt',
... r'C:\path\to\file.txt',
... r'\\host\share\path\to\file.txt',
... ]:
... print parts(path), os.path.join(*parts(path))
...
['d:\\', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt'] d:\stuff\morestuff\furtherdown\THEFILE.txt
['/', 'path', 'to', 'file.txt'] /path\to\file.txt
['', 'relative', 'path', 'to', 'file.txt'] relative\path\to\file.txt
['C:\\', 'path', 'to', 'file.txt'] C:\path\to\file.txt
['\\\\', 'host', 'share', 'path', 'to', 'file.txt'] \\host\share\path\to\file.txt
列表的第一个元素可能需要区别对待,具体取决于您要如何处理驱动器号,UNC路径以及绝对路径和相对路径。将最后一个[p]
更改为[os.path.splitdrive(p)]
会将驱动器号和目录根分成一个元组来强制解决问题。
import os
def parts(path):
p,f = os.path.split(path)
return parts(p) + [f] if f else [os.path.splitdrive(p)]
[('d:', '\\'), 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
[('', '/'), 'path', 'to', 'file.txt']
[('', ''), 'relative', 'path', 'to', 'file.txt']
[('C:', '\\'), 'path', 'to', 'file.txt']
[('', '\\\\'), 'host', 'share', 'path', 'to', 'file.txt']
编辑:我已经意识到这个答案与that given above的user1556435非常相似。由于对路径的驱动器组件的处理不同,我还是留下了我的答案。
答案 13 :(得分:0)
from os import path as os_path
然后
def split_path_iter(string, lst):
head, tail = os_path.split(string)
if head == '':
return [string] + lst
else:
return split_path_iter(head, [tail] + lst)
def split_path(string):
return split_path_iter(string, [])
或者,受上述答案启发(更优雅):
def split_path(string):
head, tail = os_path.split(string)
if head == '':
return [string]
else:
return split_path(head) + [tail]
答案 14 :(得分:0)
太可惜了! python os.path 没有类似 os.path.splitall 的东西
无论如何,这对我有用,信用:https://www.oreilly.com/library/view/python-cookbook/0596001673/ch04s16.html
import os
a = '/media//max/Data/'
def splitall(path):
# https://www.oreilly.com/library/view/python-cookbook/0596001673/ch04s16.html
allparts = []
while 1:
parts = os.path.split(path)
if parts[0] == path: # sentinel for absolute paths
allparts.insert(0, parts[0])
break
elif parts[1] == path: # sentinel for relative paths
allparts.insert(0, parts[1])
break
else:
path = parts[0]
allparts.insert(0, parts[1])
return allparts
x = splitall(a)
print(x)
z = os.path.join(*x)
print(z)
输出:
['/', 'media', 'max', 'Data', '']
/media/max/Data/
答案 15 :(得分:0)
调整了@Mike Robins的解决方案,避免在开始时使用空路径元素:
def parts(path):
p,f = os.path.split(os.path.normpath(path))
return parts(p) + [f] if f and p else [p] if p else []
os.path.normpath()
实际上只需要一次,可以在递归的单独输入函数中完成。
答案 16 :(得分:0)
非常简单的方法:
var.replace('\\', '/').split('/')
答案 17 :(得分:0)
下面的代码行可以处理:
path = re.split(r'[/// \]',path)
答案 18 :(得分:0)
我真的不确定这是否完全回答了这个问题,但是我很乐意写这个小函数来保持堆栈,坚持基于os.path的操作,并返回列表/堆栈的项目。 / p>
9 def components(path):
10 ret = []
11 while len(path) > 0:
12 path, crust = split(path)
13 ret.insert(0, crust)
14
15 return ret
16
答案 19 :(得分:0)
我使用以下内容,因为它使用os.path.basename函数,它不会向返回的列表添加任何斜杠。它也适用于任何平台的斜杠:即窗口的\\或unix的/。此外,它不会添加Windows用于服务器路径的\\\\:)
def SplitPath( split_path ):
pathSplit_lst = []
while os.path.basename(split_path):
pathSplit_lst.append( os.path.basename(split_path) )
split_path = os.path.dirname(split_path)
pathSplit_lst.reverse()
return pathSplit_lst
对于'\\\\ server \\ folder1 \\ folder2 \\ folder3 \\ folder4'
你得到了
[ '服务器', '文件夹1', '文件夹2', 'folder3', 'folder4']
答案 20 :(得分:0)
就像其他人解释的那样 - 你的问题源于使用\
,它是字符串文字/常量中的转义字符。 OTOH,如果你有来自另一个源的文件路径字符串(从文件,控制台读取或由os函数返回) - 在'\\'或r'\'上没有问题分裂。
就像其他人建议的那样,如果你想在程序文字中使用\
,你必须复制它\\
或者整个文字必须以r
作为前缀,就像所以r'lite\ral'
或r"lite\ral"
以避免解析器将\
和r
转换为CR(回车)字符。
还有一种方法 - 只是不要在代码中使用反斜杠\
路径名!自上个世纪以来,Windows识别并使用正斜杠作为目录分隔符/
的路径名正常工作!不知怎的,没有多少人知道......但是它有效:
>>> var = "d:/stuff/morestuff/furtherdown/THEFILE.txt"
>>> var.split('/')
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
顺便说一句,这将使您的代码在Unix,Windows和Mac上运行...因为所有这些代码都使用/
作为目录分隔符...即使您不想使用预定义的常量模块os
。
答案 21 :(得分:-1)
一个递归的乐趣。
这不是最优雅的答案,但应该可以在任何地方使用
import os
def split_path(path):
head = os.path.dirname(path)
tail = os.path.basename(path)
if head == os.path.dirname(head):
return [tail]
return split_path(head) + [tail]
答案 22 :(得分:-1)
使用ntpath.split()