Как разбить dos-путь на его компоненты в Python
У меня есть строковая переменная, которая представляет путь dos, например:
var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
Я хочу разбить эту строку на:
[ "d", "stuff", "morestuff", "furtherdown", "THEFILE.txt" ]
Я попытался использовать split()
и replace()
, но они либо обрабатывают первую обратную косую черту, либо вставляют шестнадцатеричные числа в строку.
Мне нужно каким-то образом преобразовать эту строковую переменную в необработанную строку, чтобы я мог ее разобрать.
Какой лучший способ сделать это?
Я также должен добавить, что содержимое var
то есть путь, который я пытаюсь проанализировать, на самом деле является возвращаемым значением запроса в командной строке. Это не путь данных, которые я генерирую сам. Его хранят в файле, а инструмент командной строки не собирается скрывать обратную косую черту.
Ответы
Ответ 1
Я был укушен много раз людьми, которые пишут свои собственные функции запуска и ошибаются. Пробелы, косые черты, обратные косые черты, двоеточия - возможности для путаницы не бесконечны, но ошибок все равно легко сделать. Поэтому я сторонник использования os.path
и рекомендую его на этой основе.
(Тем не менее, путь к добродетели не тот, который наиболее легко воспринимается, и многие люди, находив это, испытывают соблазн пройти скользкий путь прямо к проклятию. Они не поймут, что когда-нибудь все распадется, и они - или, что более вероятно, кто-то другой, - должен разобраться, почему все пошло не так, и выясняется, что кто-то сделал имя файла, которое смешивает косые черты и обратную косую черту - и кто-то предполагает, что ответ "не делать этого", Не будь ни одним из этих людей. За исключением того, кто перепутал черты и обратные косые черты - вы можете быть ими, если хотите.)
Вы можете получить файл drive и 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
Я бы сделал
import os
path = os.path.normpath(path)
path.split(os.sep)
Сначала нормализовать строку пути в правильную строку для ОС. Тогда os.sep
должен быть безопасным для использования в качестве разделителя при разделении строки.
Ответ 3
Вы можете просто использовать самый Pythonic-подход (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]
Ответ 4
В 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 на Python 3 предполагается, что вы работаете с путями 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
Ответ 5
Проблема здесь начинается с того, как вы создаете строку в первую очередь.
a = "d:\stuff\morestuff\furtherdown\THEFILE.txt"
Сделанный таким образом, Python пытается использовать специальный случай: \s
, \m
, \f
и \T
. В вашем случае \f
обрабатывается как formfeed (0x0C), в то время как другие обратные косые черты обрабатываются правильно. Что вам нужно сделать, это одно из следующих:
b = "d:\\stuff\\morestuff\\furtherdown\\THEFILE.txt" # doubled backslashes
c = r"d:\stuff\morestuff\furtherdown\THEFILE.txt" # raw string, no doubling necessary
Затем, как только вы разделите их, вы получите нужный результат.
Ответ 6
Для более краткого решения рассмотрим следующее:
def split_path(p):
a,b = os.path.split(p)
return (split_path(a) if len(a) and len(b) else []) + [b]
Ответ 7
Я не могу на самом деле внести реальный ответ на этот вопрос (поскольку я пришел сюда, надеясь найти его сам), но для меня количество различных подходов и всех упомянутых выше предостережений является самым верным показателем того, что модуль Python os.path отчаянно нуждается в этом как встроенная функция.
Ответ 8
Это работает для меня:
>>> a=r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
>>> a.split("\\")
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']
Конечно, вам может понадобиться также вырезать двоеточие из первого компонента, но сохранение его позволяет повторно собрать путь.
Модификатор r
отмечает строковый литерал как "raw"; обратите внимание, что встроенные обратные косые черты не удваиваются.
Ответ 9
Материал около mypath.split("\\")
будет лучше выражен как mypath.split(os.pathsep)
. pathsep
- разделитель путей для вашей конкретной платформы (например, \
для Windows, /
для Unix и т.д.), а сборка Python знает, какой из них использовать. Если вы используете pathsep
, тогда ваш код будет агностическим для платформы.
Ответ 10
Предположим, что у вас есть файл 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']
Ответ 11
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, просто добавьте фильтр (None, result), чтобы он удалял нежелательные "из" (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']
Ответ 12
Функциональный способ с генератором.
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']
Ответ 13
Вы можете рекурсивно 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']
Изменить: я понял, что этот ответ очень похож на указанный выше user1556435, Я оставляю свой ответ, поскольку обработка компонента привода на пути отличается.
Ответ 14
Как и другие объяснения - ваша проблема связана с использованием \
, который является символом escape в строковом литерале/константе. 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
.
Ответ 15
Я использую следующее: поскольку он использует функцию os.path.basename, он не добавляет никаких слэшей в возвращенный список. Он также работает с любыми косыми чертами: i.e window\\или unix/. Кроме того, он не добавляет \\\\, которые окна используют для путей сервера:)
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', 'folder2', 'folder3', 'Folder4']
Ответ 16
На самом деле я не уверен, что это полностью отвечает на вопрос, но мне было весело писать эту небольшую функцию, которая хранит стек, придерживается манипуляций на основе os.path и возвращает список/стек элементов.
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
Ответ 17
Ниже строка кода может обрабатывать:
- C:/путь/путь
- C://путь//путь
- C:\путь\путь
- C:\путь\путь
путь = re.split(r '[///\]', путь)
Ответ 18
использовать ntpath.split()