Как разбить 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

Ниже строка кода может обрабатывать:

  1. C:/путь/путь
  2. C://путь//путь
  3. C:\путь\путь
  4. C:\путь\путь

путь = re.split(r '[///\]', путь)

Ответ 18

использовать ntpath.split()