วิธีการแยกเส้นทาง DOS เป็นส่วนประกอบใน Python


153

ฉันมีตัวแปรสตริงซึ่งแสดงถึงเส้นทาง DOS เช่น:

var = "d:\stuff\morestuff\furtherdown\THEFILE.txt"

ฉันต้องการแยกสตริงนี้เป็น:

[ "d", "stuff", "morestuff", "furtherdown", "THEFILE.txt" ]

ฉันได้ลองใช้split()และreplace()พวกเขาอาจดำเนินการเพียงเครื่องหมายทับขวาแรกหรือพวกเขาแทรกตัวเลขฐานสิบหกลงในสตริง

ฉันต้องการแปลงตัวแปรสตริงนี้เป็นสตริงดิบอย่างใดเพื่อให้ฉันสามารถแยกมัน

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?

ฉันควรเพิ่มว่าเนื้อหาของvarเช่นเส้นทางที่ฉันพยายามแยกเป็นจริงแล้วคืนค่าของแบบสอบถามบรรทัดคำสั่ง ไม่ใช่ข้อมูลพา ธ ที่ฉันสร้างขึ้นเอง มันเก็บไว้ในไฟล์และเครื่องมือบรรทัดคำสั่งจะไม่หลบหนีแบ็กสแลช


6
ในขณะที่คุณทบทวนคำตอบเหล่านี้โปรดจำไว้ว่าos.path.splitมันไม่ได้ผลสำหรับคุณเพราะคุณไม่ได้ใช้สตริงนั้นอย่างถูกต้อง
Jed Smith

คุณต้องหนีจากสตริงหรือใช้ rawstring: r"d:\stuff\morestuff\furtherdown\THEFILE.txt"เพื่อป้องกันสิ่งต่าง ๆ เช่น\sถูกตีความผิด
smci

คำตอบ:


164

ฉันถูกคนจำนวนมากกัดเวลาเขียนฟังก์ชั่นเล่นซอของตัวเองและทำให้มันผิด ช่องว่าง, สแลช, แบ็กสแลช, โคลอน - ความเป็นไปได้สำหรับความสับสนนั้นไม่มีที่สิ้นสุด แต่ความผิดพลาดนั้นเกิดขึ้นได้ง่าย ดังนั้นฉันจึงชอบใช้งาน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หากเส้นทางเดิมแน่นอนคุณอาจสูญเสียรหัสเล็กน้อยหากคุณไม่ต้องการที่)


@brone - ฉันชอบที่จะใช้วิธีนี้มากกว่าที่จะต้องกังวลเกี่ยวกับการหลบแบ็กสแลช ขอบคุณ!
BeeBand

1
ฉันยินดีที่จะได้รับการพิสูจน์ผิด แต่ดูเหมือนว่าฉันจะแนะนำวิธีการแก้ปัญหาไม่ทำงานหากเส้นทางเช่นนี้ "C: \ usr \ rs0 \ my0 \ in111102.log" ถูกใช้ (เว้นแต่อินพุตเริ่มต้นเป็นสตริงดิบ )
shearichard

1
ดูเหมือนว่าสิ่งนี้จะไม่แยกเส้นทางอย่างถูกต้องหากมันมีเพียงไดเรกทอรีใน OSX เช่น "/ path / to / my / folder /" เพื่อให้บรรลุว่าคุณต้องการเพิ่มสองบรรทัดนี้ไปยังจุดเริ่มต้น: และif path.endswith("/"): path = path[:-1]
เควินลอนดอน

1
ฉันชอบวิธีแก้ปัญหาโดย @Tompa
jaycode

1
ผมเห็นด้วยกับjaycode : Tompa 's วิธีการแก้ปัญหาคือวิธีการที่ยอมรับและควรได้รับการตอบรับ ทางเลือกที่ซับซ้อนไม่มีประสิทธิภาพและมีข้อผิดพลาดมากเกินไปนี้ไม่สามารถส่งรหัสผ่านการผลิตได้ มีไม่มีเหตุผลที่เหมาะสมที่จะพยายาม ( ... และล้มเหลวของหลักสูตร) ที่จะแยกออกจากกันซ้ำ pathnames เมื่อแยกสตริงง่ายประสบความสำเร็จมีเพียงบรรทัดเดียวของรหัส
เซซิลแกงกะหรี่

287

ฉันจะทำ

import os
path = os.path.normpath(path)
path.split(os.sep)

อันดับแรกให้ทำให้สตริงเส้นทางเป็นมาตรฐานที่เหมาะสมสำหรับระบบปฏิบัติการ จากนั้นos.sepจะต้องปลอดภัยที่จะใช้เป็นตัวคั่นในการแยกฟังก์ชั่นสตริง


25
คำตอบที่แท้จริงเพียงข้อเดียว: มันเกิดขึ้นแล้ว วิธีการแก้ปัญหาที่ยอมรับได้เป็นวิธีที่ง่ายที่สุดแน่นอน ดูเถิด! เพราะมันเป็นสิ่งที่สวยงามและน่าดูและไม่มีกรณีขอบ
เซซิลแกง

20
ในฐานะหนึ่งในสายการบินos.path.normpath(a_path).split(os.path.sep)
แดเนียลฟา

2
ดูเหมือนว่านี่จะใช้งานไม่ได้กับ path = root ในกรณีดังกล่าวผลลัพธ์ของ path.split คือ ['', ''] โดยทั่วไปแล้วโซลูชัน split () นี้ให้ไดเรกทอรีด้านซ้ายสุดที่มีชื่อสตริงว่าง (ซึ่งอาจถูกแทนที่ด้วยเครื่องหมายทับที่เหมาะสม) ปัญหาหลักคือการที่เฉือนเดียว (ข้างหน้าหรือถอยหลังขึ้นอยู่กับระบบปฏิบัติการ) เป็นชื่อของไดเรกทอรีรากในขณะที่คนอื่น ๆ ในเส้นทางที่จะเป็นตัวคั่น
gwideman

2
มันจะทำงานได้ดีขึ้นเมื่อใช้ lstrip หรือไม่? os.path.normpath(path).lstrip(os.path.sep).split(os.path.sep)
Vidar

1
@ user60561 นั่นเป็นเพราะบน Linux แบ็กสแลชเป็นอักขระที่อนุญาตให้ใช้ในชื่อไฟล์ นั่นเป็นเหตุผลว่าทำไมใน Windows normpathจะรับรู้ว่าเครื่องหมายทับซ้ายเป็นตัวคั่น บน Linux normpathก็จะสมมติว่าคุณมีไดเรกทอรีที่เรียกว่าและแฟ้มหรือไดเรกทอรีภายในนั้นเรียกว่า\1\2 3
Vojislav Stojkovic

81

คุณสามารถใช้วิธีการ 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]

22
some timesงานนี้ เวลาอื่น (อย่างน้อยใน windows) คุณจะพบเส้นทางที่มีลักษณะfolder\folder2\folder3/file.txtดังนี้ มันจะดีกว่าที่จะทำให้ปกติ (os.path.normpath) เส้นทางแรกแล้วแยกมัน
vikki

7
คำตอบนี้เกือบจะมี ตามที่vikkiแนะนำความล้มเหลวในการทำให้ปกติชื่อพา ธ ก่อนที่จะแยกสตริงคาถาลงโทษในกรณีขอบทั่วไป (เช่น/foo//bar) ดูคำตอบของTompaเพื่อหาคำตอบที่แข็งแกร่งยิ่งขึ้น
เซซิลแกง

62

ใน 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 และใน * ระวังจะถือว่าคุณกำลังทำงานกับเส้นทาง 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')

แก้ไข: นอกจากนี้ยังมี backport เป็น python 2 ที่มีอยู่: pathlib2


3
Path.parts เป็นสิ่งที่ฉันต้องการเสมอ แต่ฉันไม่เคยรู้มาก่อนจนกระทั่งทุกวันนี้
JamEnergy

ทำไมสิ่งนี้ถึงไม่ถูกห่อหุ้มด้วยฟังก์ชั่นไพ ธ อลที่ดี?
Eduardo Pignatelli

2
นั่นคือคำตอบ!
nayriz

11

ปัญหาที่นี่เริ่มต้นด้วยวิธีที่คุณสร้างสตริงในตอนแรก

a = "d:\stuff\morestuff\furtherdown\THEFILE.txt"

ทำวิธีนี้งูใหญ่พยายามที่จะกรณีพิเศษเหล่านี้: \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

จากนั้นเมื่อคุณแยกสิ่งเหล่านี้แล้วคุณจะได้ผลลัพธ์ที่ต้องการ


@W Craig Trader - ขอบคุณ แต่เส้นทางนี้ไม่ใช่เส้นทางที่ฉันสร้างขึ้นเอง - มันกลับมาหาฉันจากโปรแกรมอื่นและฉันต้องเก็บข้อมูลนี้ไว้ในตัวแปร ฉันไม่แน่ใจว่าจะแปลงข้อมูลที่เก็บไว้ในตัวแปรเป็น "ข้อความดิบ" ได้อย่างไร
BeeBand

ไม่มีสิ่งเช่น "ข้อความดิบ" ... เป็นเพียงวิธีที่คุณนำเสนอในแหล่งที่มา อาจเติม r "" ลงในสตริงหรือส่งผ่าน. แทนที่ ('\\', '/')
Marco Mariani

@BeeBand คุณจะรับข้อมูลกลับมาจากโปรแกรมอื่นได้อย่างไร คุณอ่านมันจากไฟล์, ไปป์, ซ็อกเก็ตหรือไม่? ถ้าเป็นเช่นนั้นคุณไม่จำเป็นต้องทำอะไรแฟนซี เหตุผลเดียวในการเพิ่มแบ็กสแลชสองเท่าหรือการใช้สตริงดิบคือการใส่ค่าคงที่สตริงลงในรหัส Python ในทางกลับกันหากโปรแกรมอื่นกำลังสร้างแบ็กสแลชสองเท่าจากนั้นคุณต้องการล้างข้อมูลนั้นก่อนที่จะแยกเส้นทางของคุณ
Craig Trader

@W Craig Trader - ฉันกำลังอ่านจากไฟล์ที่เขียนโดยโปรแกรมอื่น ฉันไม่สามารถได้รับsplit()หรือreplace()การทำงานด้วยเหตุผลบางอย่าง - ฉันเก็บรับค่าฐานสิบหก คุณพูดถูกฉันคิดว่าฉันเห่าต้นไม้ผิดด้วยแนวคิดสตริงดิบ - ฉันคิดว่าฉันใช้split()ไม่ถูกต้อง เพราะฉันลองใช้วิธีแก้ไขปัญหาบางอย่างโดยใช้วิธีนี้split()และมันใช้ได้กับฉันในตอนนี้
BeeBand

10

สำหรับวิธีแก้ปัญหาที่ค่อนข้างกระชับกว่าให้พิจารณาสิ่งต่อไปนี้:

def split_path(p):
    a,b = os.path.split(p)
    return (split_path(a) if len(a) and len(b) else []) + [b]

นี่คือทางออกที่ฉันโปรดปรานสำหรับปัญหานี้ ดีมาก.
Will Moore

1
/นี้จะไม่ทำงานถ้าปลายเส้นทางด้วย นอกจากนี้ยังให้สตริงว่างที่จุดเริ่มต้นของรายการหากเส้นทางของคุณเริ่มต้นด้วย/
Sorig

4

จริง ๆ แล้วฉันไม่สามารถให้คำตอบที่แท้จริงกับสิ่งนี้ (เมื่อฉันมาที่นี่หวังว่าจะได้พบกับตัวเอง) แต่สำหรับฉันจำนวนของวิธีการที่แตกต่างกันและคำเตือนทั้งหมดที่กล่าวถึงเป็นตัวบ่งชี้ที่แน่นอนที่สุดว่า เป็นฟังก์ชั่นในตัว


4

วิธีการทำงานกับเครื่องกำเนิดไฟฟ้า

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']

3

มันเหมาะกับฉัน:

>>> a=r"d:\stuff\morestuff\furtherdown\THEFILE.txt"
>>> a.split("\\")
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

แน่นอนว่าคุณอาจจำเป็นต้องตัดเครื่องหมายโคลอนออกจากองค์ประกอบแรก แต่การทำให้มันเป็นไปได้ที่จะรวบรวมเส้นทางอีกครั้ง

rปรับปรุงเครื่องหมายอักษรสตริงเป็น "ดิบ"; สังเกตว่าแบ็กสแลชที่ฝังไว้นั้นไม่ได้เพิ่มเป็นสองเท่า


@unwind - rข้างหน้าสตริงของคุณนั่นหมายถึงอะไร?
BeeBand

2
r หมายถึงสตริงดิบ - มันจะหนี\ อักขระโดยอัตโนมัติ มันมีประโยชน์ที่จะใช้เมื่อใดก็ตามที่คุณทำเส้นทาง
Wayne Werner

1
@BeeBand: คุณไม่จำเป็นต้องสนใจ r "" เป็นเพียงบางสิ่งที่สำคัญในระหว่างการรวบรวม / การแยกวิเคราะห์โค้ดไม่ใช่สิ่งที่กลายเป็นคุณสมบัติของสตริงที่ถูกวิเคราะห์คำครั้งเดียว มันหมายถึง "นี่เป็นตัวอักษรสตริง แต่ไม่ตีความแบ็กสแลชใด ๆ ว่ามีความหมายอื่นใดนอกจากเป็นแบ็กสแลช"
คลาย

3
ฉันคิดว่ามันอาจจะมีประโยชน์ที่จะพูดถึงคุณลบด้วยความคลุมเครือมากขึ้นโดยใช้ a.split (os.sep) แทนการเข้ารหัสอย่างหนัก?
Tim McJilton

4
ฉันต้องลงคะแนนให้คุณเพราะไม่มีโอกาสอธิบายos.path.splitและos.pathsepพิจารณาว่าทั้งสองแบบพกพาได้ดีกว่าที่คุณเขียน มันอาจไม่สำคัญสำหรับ OP ตอนนี้ แต่เมื่อเขาเขียนสิ่งที่ต้องการย้ายแพลตฟอร์ม
Jed Smith

3

สิ่งที่เกี่ยวกับเกี่ยวกับจะมีการแสดงที่ดีกว่าmypath.split("\\") เป็นตัวแยกพา ธ สำหรับแพลตฟอร์มเฉพาะของคุณ (เช่นสำหรับ Windows, Unix และอื่น ๆ ) และ Python build รู้ว่าควรใช้อันไหน หากคุณใช้รหัสของคุณจะไม่เชื่อเรื่องพระเจ้าmypath.split(os.sep)sep\/sep


1
os.path.splitหรือ คุณต้องการที่จะระวังos.pathsepเพราะมันเป็น:เวอร์ชั่น Python ของฉันใน OS X (และos.path.splitจัดการอย่างถูกต้อง/)
Jed Smith

4
คุณหมายถึงไม่ได้os.sep os.pathsepปฏิบัติตามภูมิปัญญาในos.sepเอกสาร: โปรดทราบว่าการรู้ว่าสิ่งนี้ไม่เพียงพอที่จะแยกวิเคราะห์หรือเชื่อมโยงชื่อพา ธ - ใช้ os.path.split () และ os.path.join ()
Jon-Eric

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 เพียงเพิ่มตัวกรอง (ไม่มีผล) ดังนั้นมันจะลบ '' ที่ไม่ต้องการออกจากการแยก () เนื่องจากเส้นทางเหล่านั้นเริ่มต้นด้วย '/' หรือ '//' เช่น '// 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']

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']

แก้ไข: ฉันได้ตระหนักว่าคำตอบนี้จะคล้ายกับที่ดังกล่าวข้างต้นโดยuser1556435 ฉันทิ้งคำตอบไว้เนื่องจากการจัดการส่วนประกอบของไดรฟ์ของเส้นทางนั้นแตกต่างกัน


0

เช่นเดียวกับคนอื่น ๆ อธิบาย - ปัญหาของคุณเกิดจากการใช้\ซึ่งเป็นตัวหนีในสตริงตัวอักษร / คงที่ OTOH ถ้าคุณมีสตริงพา ธ ของไฟล์นั้นจากแหล่งอื่น (อ่านจากไฟล์คอนโซลหรือส่งคืนโดยฟังก์ชั่นระบบปฏิบัติการ) - จะไม่มีปัญหาในการแยก '\\' หรือ r '\'

และเช่นเดียวกับที่คนอื่น ๆ แนะนำถ้าคุณต้องการที่จะใช้\ในโปรแกรมตัวอักษรคุณต้องทำซ้ำมัน\\หรือตัวอักษรทั้งหมดจะต้องมีคำนำหน้าโดยrเช่นนั้นr'lite\ral'หรือr"lite\ral"เพื่อหลีกเลี่ยง parser แปลงตัวอักษร\และrCR (carriage return)

มีอีกวิธีหนึ่งคือ - อย่าใช้\ชื่อเส้นทางเครื่องหมายทับขวาในรหัสของคุณ! ตั้งแต่ศตวรรษที่แล้ว Windows จดจำและทำงานได้ดีกับชื่อพา ธ ที่ใช้เครื่องหมายทับซ้ายเป็นตัวคั่นไดเรกทอรี/! ยังมีอีกไม่กี่คนที่รู้ว่า .. แต่มันได้ผล:

>>> var = "d:/stuff/morestuff/furtherdown/THEFILE.txt"
>>> var.split('/')
['d:', 'stuff', 'morestuff', 'furtherdown', 'THEFILE.txt']

นี้โดยวิธีการที่จะทำให้การทำงานของรหัสของคุณบน Unix, Windows และ Mac ... เพราะทั้งหมดของพวกเขาจะใช้/เป็นตัวคั่นไดเรกทอรี ... osแม้ว่าคุณไม่ต้องการที่จะใช้ค่าคงที่ที่กำหนดไว้ล่วงหน้าของโมดูล


น่าเสียดายที่ข้อมูลกำลังถูกส่งคืนให้ฉันจากโปรแกรมอื่นที่ฉันเรียกใช้จากสคริปต์ของหลาม ฉันไม่สามารถควบคุมได้ว่าจะใช้ '\' หรือ '/' - เป็นโปรแกรมของบุคคลที่สามที่กำหนดสิ่งนี้ (อาจใช้แพลตฟอร์ม)
BeeBand

@BeeBand: อ่าคุณจะไม่มีปัญหาในระหว่างการทดสอบเมื่อคุณให้สตริงเป็นตัวอักษรในโปรแกรมของคุณ หรือคุณสามารถทำการแฮ็คความชั่วร้ายต่อไปนี้หลังจากได้รับเส้นทาง: var = var.replace('\\','/')- แทนที่ \ with / และทำงานต่อไปกับสแลชเท่านั้น :)
Nas Banov

นั่นคือการแฮ็คที่ชั่วร้าย: o)
BeeBand

@BeeBand: นั่นคือเหตุผลที่ฉันเตือน เมื่อฉันพูดอะไรบางอย่างที่ชั่วร้ายฉันไม่ได้หมายความว่าไม่ควรใช้ แต่ก็ควรระวังให้มากว่าทำไมพวกเขาถึงใช้มันและแจ้งเตือนถึงผลที่ไม่ตั้งใจ ในกรณีนี้ผลลัพธ์ที่ไม่น่าเป็นไปได้มากคือถ้าใช้กับระบบไฟล์ Unix ที่มี `` การใช้งานในชื่อไฟล์หรือไดเรกทอรี (มันยากมาก แต่เป็นไปได้) - รหัสนี้จะ 'แตก'
Nas Banov

0

สมมติว่าคุณมีไฟล์ที่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']

มันใช้งานได้จริงขอบคุณ! แต่ฉันเลือกวิธีแก้ปัญหาของ brone เพราะฉันไม่ต้องการกังวลกับการหลบหลีกแบ็กสแลช
BeeBand

9
ไม่ pythonic เนื่องจากมันขึ้นอยู่กับระบบไฟล์
jb

0

ฉันใช้สิ่งต่อไปนี้เนื่องจากใช้ฟังก์ชัน os.path.basename จึงไม่เพิ่มเครื่องหมายทับลงในรายการที่ส่งคืน นอกจากนี้ยังทำงานร่วมกับเครื่องหมายทับของแพลตฟอร์มใด ๆ : เช่น \\ window หรือ unix's / และยิ่งกว่านั้นมันไม่ได้เพิ่ม \\\\ ที่ 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

ดังนั้นสำหรับ '\\\\ เซิร์ฟเวอร์ \\ โฟลเดอร์ 1 \\ โฟลเดอร์ 2 \\ โฟลเดอร์ 3 \\ โฟลเดอร์ 4'

คุณได้รับ

[ 'เซิร์ฟเวอร์', 'folder1', 'folder2', 'folder3', 'folder4']


1
ไม่เป็นไปตามค่าคงที่ที่ส่งผลลัพธ์ของคุณไปให้os.path.join()ควรส่งคืนสตริงต้นฉบับ [r'\\','server','folder1','folder2','folder3','folder4']ผมว่าการส่งออกที่ถูกต้องสำหรับการป้อนข้อมูลตัวอย่างของคุณคือ คือสิ่งที่os.path.split()ไม่
Jon-Eric

0

ฉันไม่แน่ใจจริงๆว่าสิ่งนี้ตอบคำถามได้อย่างสมบูรณ์หรือไม่ แต่ฉันมีเวลาเขียนฟังก์ชั่นเล็ก ๆ น้อย ๆ ที่เก็บสแต็คยึดติดกับระบบปฏิบัติการ 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

0

บรรทัดด้านล่างของรหัสสามารถจัดการได้:

  1. C: / เส้นทาง / เส้นทาง
  2. C: // เส้นทางเส้นทาง //
  3. C: \ เส้นทาง \ เส้นทาง
  4. C: \ เส้นทาง \ เส้นทาง

path = re.split (r '[/// \]', พา ธ )


0

หนึ่งวนเวียนเพื่อความสนุก

ไม่ใช่คำตอบที่หรูหราที่สุด แต่ควรทำงานได้ทุกที่:

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]

ขอโทษจริงๆ ควรอ่านคำถามอย่างละเอียด ... เส้นทาง 'ดอส'
DuGNu

-1

ใช้ ntpath.split()


เมื่อฉันใช้ os.path.split () ฉันได้รับ, ( d:\\stuff, morestuff\x0curtherdown\thefile.mux)
BeeBand

ดังที่ BeeBand ระบุไว้ os.path.split () ไม่ได้ทำสิ่งที่ต้องการจริงๆ
คลาย

ขอโทษฉันเพิ่งรู้ว่า os.path ทำงานได้เฉพาะกับระบบปฏิบัติการของคุณ ntpath จะแยกเส้นทาง DOS
deft_code

แม้จะมี ntpath ฉันก็ยังได้รับd:\\stuff, morestuff\x0curtherdown\thefile.mux
BeeBand

2
@BeeBand: มีปัญหากับการหนีสตริงของคุณ '\x0c'เป็นอักขระฟีดฟอร์ม วิธีสร้างอักขระป้อนฟอร์มคือ '\ f' ถ้าคุณต้องการสตริงตัวอักษร '\ f' จริงๆคุณมีสองตัวเลือก: หรือ'\\f' r'\f'
deft_code
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.