파이썬에서 dos 경로를 구성 요소로 분할하는 방법
dos 경로를 나타내는 문자열 변수가 있습니다.
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
이 문자열을 다음과 같이 나누고 싶습니다.
[ "d", "stuff", "morestuff", "furtherdown", "THEFILE.txt" ]
내가 사용하는 시도 split()
하고 replace()
있지만, 어느 단지 문자열로 진수 번호 삽입 최초의 백 슬래시 또는를 처리합니다.
어떻게 든이 문자열 변수를 원시 문자열로 변환하여 구문 분석 할 수 있어야합니다.
가장 좋은 방법은 무엇입니까?
또한 var
구문 분석하려는 경로 의 내용 이 실제로 명령 줄 쿼리의 반환 값임을 추가해야합니다. 내가 생성하는 경로 데이터가 아닙니다. 파일에 저장되며 명령 행 도구는 백 슬래시를 이스케이프하지 않습니다.
나는 사람들이 자신의 길 찾기 기능을 작성하고 잘못함으로써 많은 시간을 물었습니다. 공백, 슬래시, 백 슬래시, 콜론-혼란의 가능성은 끝이 없지만 실수는 쉽게 이루어집니다. 그래서 나는의 사용을위한 stickler이며 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
. 원하지 않으면 약간의 코드를 잃을 수 있습니다.)
난 그럴거야
import os
path = os.path.normpath(path)
path.split(os.sep)
먼저 경로 문자열을 OS에 적합한 문자열로 정규화하십시오. 그런 다음 os.sep
문자열 함수 분할에서 구분 기호로 사용하기에 안전해야합니다.
가장 파이썬적인 접근 방식 (IMHO)을 간단히 사용할 수 있습니다.
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]
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')
On a Windows install of Python 3 this will assume that you are working with Windows paths, and on *nix it will assume that you are working with posix paths. This is usually what you want, but if it isn't you can use the classes pathlib.PurePosixPath
or pathlib.PureWindowsPath
as needed:
>>> 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')
Edit: There is also a backport to python 2 available: pathlib2
The problem here starts with how you're creating the string in the first place.
a = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
Done this way, Python is trying to special case these: \s
, \m
, \f
, and \T
. In your case, \f
is being treated as a formfeed (0x0C) while the other backslashes are handled correctly. What you need to do is one of these:
b = "d:\\stuff\\morestuff\\furtherdown\\THEFILE.txt" # doubled backslashes
c = r"d:\stuff\morestuff\furtherdown\THEFILE.txt" # raw string, no doubling necessary
Then once you split either of these, you'll get the result you want.
For a somewhat more concise solution, consider the following:
def split_path(p):
a,b = os.path.split(p)
return (split_path(a) if len(a) and len(b) else []) + [b]
I can't actually contribute a real answer to this one (as I came here hoping to find one myself), but to me the number of differing approaches and all the caveats mentioned is the surest indicator that Python's os.path module desperately needs this as a built-in function.
It works for me:
>>> a=r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
>>> a.split("\\")
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
Sure you might need to also strip out the colon from the first component, but keeping it makes it possible to re-assemble the path.
The r
modifier marks the string literal as "raw"; notice how embedded backslashes are not doubled.
Let assume you have have a file filedata.txt
with content:
d:\stuff\morestuff\furtherdown\THEFILE.txt
d:\otherstuff\something\otherfile.txt
You can read and split the file paths:
>>> for i in open("filedata.txt").readlines():
... print i.strip().split("\\")
...
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
['d:', 'otherstuff', 'something', 'otherfile.txt']
The stuff about about mypath.split("\\")
would be better expressed as mypath.split(os.pathsep)
. pathsep
is the path separator for your particular platform (e.g., \
for Windows, /
for Unix, etc.), and the Python build knows which one to use. If you use pathsep
, then your code will be platform agnostic.
re.split() can help a little more then string.split()
import re
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
re.split( r'[\\/]', var )
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
If you also want to support Linux and Mac paths, just add filter(None,result), so it will remove the unwanted '' from the split() since their paths starts with '/' or '//'. for example '//mount/...' or '/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']
The functional way, with a generator.
def split(path):
(drive, head) = os.path.splitdrive(path)
while (head != os.sep):
(head, tail) = os.path.split(head)
yield tail
In action:
>>> print([x for x in split(os.path.normpath('/path/to/filename'))])
['filename', 'to', 'path']
You can recursively os.path.split
the string
import os
def parts(path):
p,f = os.path.split(path)
return parts(p) + [f] if f else [p]
Testing this against some path strings, and reassembling the path with 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
The first element of the list may need to be treated differently depending on how you want to deal with drive letters, UNC paths and absolute and relative paths. Changing the last [p]
to [os.path.splitdrive(p)]
forces the issue by splitting the drive letter and directory root out into a tuple.
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']
Edit: I have realised that this answer is very similar to that given above by user1556435. I'm leaving my answer up as the handling of the drive component of the path is different.
Just like others explained - your problem stemmed from using \
, which is escape character in string literal/constant. OTOH, if you had that file path string from another source (read from file, console or returned by os function) - there wouldn't have been problem splitting on '\\' or r'\'.
And just like others suggested, if you want to use \
in program literal, you have to either duplicate it \\
or the whole literal has to be prefixed by r
, like so r'lite\ral'
or r"lite\ral"
to avoid the parser converting that \
and r
to CR (carriage return) character.
There is one more way though - just don't use backslash \
pathnames in your code! Since last century Windows recognizes and works fine with pathnames which use forward slash as directory separator /
! Somehow not many people know that.. but it works:
>>> var = "d:/stuff/morestuff/furtherdown/THEFILE.txt"
>>> var.split('/')
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
This by the way will make your code work on Unix, Windows and Mac... because all of them do use /
as directory separator... even if you don't want to use the predefined constants of module os
.
I use the following as since it uses the os.path.basename function it doesn't add any slashes to the returned list. It also works with any platform's slashes: i.e window's \\ or unix's /. And furthermore, it doesn't add the \\\\ that windows uses for server paths :)
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
So for '\\\\server\\folder1\\folder2\\folder3\\folder4'
you get
['server','folder1','folder2','folder3','folder4']
I'm not actually sure if this fully answers the question, but I had a fun time writing this little function that keeps a stack, sticks to os.path-based manipulations, and returns the list/stack of items.
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
Below line of code can handle:
- C:/path/path
- C://path//path
- C:\path\path
- C:\path\path
path = re.split(r'[///\]', path)
use ntpath.split()
참고URL : https://stackoverflow.com/questions/3167154/how-to-split-a-dos-path-into-its-components-in-python
'IT' 카테고리의 다른 글
작업 표시 줄을 영구적으로 비활성화하는 방법 (0) | 2020.07.03 |
---|---|
버튼 그림자를 제거하는 방법 (Android) (0) | 2020.07.03 |
UITableView 섹션 헤더의 글꼴 크기 변경 (0) | 2020.07.03 |
UITextField의 시작 부분에 공간을 만듭니다. (0) | 2020.07.03 |
Xcode에서 더 이상 사용되지 않는 경고 억제 (0) | 2020.07.03 |