Câu trả lời:
Sử dụng os.path.split
hoặc os.path.basename
như những người khác đề xuất sẽ không hoạt động trong mọi trường hợp: nếu bạn đang chạy tập lệnh trên Linux và cố gắng xử lý một đường dẫn kiểu cửa sổ cổ điển, nó sẽ thất bại.
Đường dẫn Windows có thể sử dụng dấu gạch chéo ngược hoặc dấu gạch chéo chuyển tiếp làm dấu phân cách đường dẫn. Do đó, ntpath
mô-đun (tương đương với os.path khi chạy trên windows) sẽ hoạt động cho tất cả (1) đường dẫn trên tất cả các nền tảng.
import ntpath
ntpath.basename("a/b/c")
Tất nhiên, nếu tệp kết thúc bằng dấu gạch chéo, tên cơ sở sẽ trống, vì vậy hãy tạo chức năng của riêng bạn để xử lý:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Xác minh:
>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [path_leaf(path) for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']
(1) Có một cảnh báo: Tên tệp Linux có thể chứa dấu gạch chéo ngược . Vì vậy, trên linux, r'a/b\c'
luôn đề cập đến tệp b\c
trong a
thư mục, trong khi trên Windows, nó luôn đề cập đến c
tệp trong b
thư mục con của a
thư mục. Vì vậy, khi cả dấu gạch chéo tiến và lùi được sử dụng trong một đường dẫn, bạn cần biết nền tảng liên quan để có thể diễn giải chính xác. Trong thực tế, thường an toàn khi cho rằng đó là đường dẫn cửa sổ vì dấu gạch chéo ngược hiếm khi được sử dụng trong tên tệp Linux, nhưng hãy ghi nhớ điều này khi bạn viết mã để bạn không tạo ra các lỗ hổng bảo mật ngẫu nhiên.
r'C:\path\to\file.txt'
:) trên máy Linux, bạn mới cần sử dụng mô-đun ntpath. Nếu không, bạn có thể sử dụng các chức năng từ os.path. Điều này là do các hệ thống Linux thường cho phép sử dụng các ký tự dấu gạch chéo ngược trong tên tệp (như được giải thích trong câu trả lời).
os.path.basename(os.path.normpath(path))
?
Trên thực tế, có một hàm trả về chính xác những gì bạn muốn
import os
print(os.path.basename(your_path))
os.path.basename(your_path)
Điều này đã làm việc! Tôi muốn đường dẫn kịch bản: os.path.dirname(os.path.realpath(__file__))
và tên tập lệnh : os.path.basename(os.path.realpath(__file__))
. Cảm ơn!
'C:\\temp\\bla.txt'
thay thế.
os.path.split là chức năng bạn đang tìm kiếm
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
import os
head, tail = os.path.split('path/to/file.exe')
đuôi là những gì bạn muốn, tên tệp.
Xem tài liệu mô-đun os python để biết chi tiết
import os
file_location = '/srv/volume1/data/eds/eds_report.csv'
file_name = os.path.basename(file_location ) #eds_report.csv
location = os.path.dirname(file_location ) #/srv/volume1/data/eds
Trong ví dụ của bạn, bạn cũng sẽ cần phải cắt dấu gạch chéo từ bên phải để trả về c
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Cấp độ thứ hai:
>>> os.path.filename(os.path.dirname(path))
'b'
cập nhật: Tôi nghĩ lazyr
đã cung cấp câu trả lời đúng. Mã của tôi sẽ không hoạt động với các đường dẫn giống như windows trên các hệ thống unix và ngược lại với các đường dẫn giống như unix trên hệ thống windows.
r"a\b\c"
trên linux, cũng như "a/b/c"
trên windows.
os.path.basename(path)
sẽ chỉ làm việc nếu os.path.isfile(path)
có True
. Do đó, hoàn toàn path = 'a/b/c/'
không phải là một tên tệp hợp lệ ...
os.path.basename("a/b/c/")
trở lại ""
vì dấu gạch chéo.
lazyr
bạn đúng rồi! Tôi đã không nghĩ về điều đó. Nó sẽ được an toàn để làm path = path.replace('\\', '/')
?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
cái này sẽ trả về: paint.exe
thay đổi giá trị sep của hàm phân tách liên quan đến đường dẫn hoặc hệ điều hành của bạn.
fname = str(path).split('/')[-1]
Nếu đường dẫn tệp của bạn không kết thúc bằng "/" và các thư mục được phân tách bằng "/" thì hãy sử dụng mã sau đây. Như chúng ta biết, đường dẫn thường không kết thúc bằng "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Nhưng trong một số trường hợp như URL kết thúc bằng "/" thì hãy sử dụng mã sau
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
nhưng khi đường dẫn của bạn được đặt bởi "\" mà bạn thường tìm thấy trong các đường dẫn windows thì bạn có thể sử dụng các mã sau
import os
path_str = "c:\\var\www\index.html"
print(os.path.basename(path_str))
import os
path_str = "c:\\home\some_str\last_str\\"
split_path = path_str.rsplit("\\",1)
print(os.path.basename(split_path[0]))
Bạn có thể kết hợp cả hai thành một chức năng bằng cách kiểm tra loại HĐH và trả về kết quả.
Điều này đang làm việc cho linux và windows cũng như với thư viện tiêu chuẩn
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
'a/b/../../a/b/c/', 'a/b/../../a/b/c']
def path_leaf(path):
return path.strip('/').strip('\\').split('/')[-1].split('\\')[-1]
[path_leaf(path) for path in paths]
Các kết quả:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Đây là một giải pháp chỉ dành cho regex, dường như hoạt động với mọi đường dẫn HĐH trên mọi HĐH.
Không có mô-đun nào khác là cần thiết và cũng không cần tiền xử lý:
import re
def extract_basename(path):
"""Extracts basename of a given path. Should Work with any OS Path on any OS"""
basename = re.search(r'[^\\/]+(?=[\\/]?$)', path)
if basename:
return basename.group(0)
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
'a/b/../../a/b/c/', 'a/b/../../a/b/c']
print([extract_basename(path) for path in paths])
# ['c', 'c', 'c', 'c', 'c', 'c', 'c']
extra_paths = ['C:\\', 'alone', '/a/space in filename', 'C:\\multi\nline']
print([extract_basename(path) for path in extra_paths])
# ['C:', 'alone', 'space in filename', 'multi\nline']
Cập nhật:
Nếu bạn chỉ muốn một tên tệp tiềm năng , nếu có (nghĩa /a/b/
là một thư mục và cũng vậy c:\windows\
), hãy thay đổi biểu thức chính quy thành : r'[^\\/]+(?![\\/])$'
. Đối với "regex bị thách thức", điều này sẽ thay đổi giao diện chuyển tiếp tích cực đối với một loại dấu gạch chéo thành một cái nhìn về phía trước tiêu cực, khiến các tên đường dẫn kết thúc bằng dấu gạch chéo không trả về gì thay vì thư mục con cuối cùng trong tên đường dẫn. Tất nhiên, không có gì đảm bảo rằng tên tệp tiềm năng thực sự đề cập đến một tệp và cho điều đó os.path.is_dir()
hoặc os.path.is_file()
sẽ cần phải được sử dụng.
Điều này sẽ phù hợp như sau:
/a/b/c/ # nothing, pathname ends with the dir 'c'
c:\windows\ # nothing, pathname ends with the dir 'windows'
c:hello.txt # matches potential filename 'hello.txt'
~it_s_me/.bashrc # matches potential filename '.bashrc'
c:\windows\system32 # matches potential filename 'system32', except
# that is obviously a dir. os.path.is_dir()
# should be used to tell us for sure
Regex có thể được kiểm tra ở đây .
Có lẽ chỉ là tất cả trong một giải pháp của tôi mà không quan trọng một số giải pháp mới (liên quan đến tempfile để tạo các tệp tạm thời: D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Lấy các giá trị của abc.name
sẽ là một chuỗi như thế này: '/tmp/tmpks5oksk7'
Vì vậy, tôi có thể thay thế /
bằng một khoảng trắng .replace("/", " ")
và sau đó gọi split()
. Điều đó sẽ trả về một danh sách và tôi nhận được phần tử cuối cùng của danh sách với[-1]
Không cần phải có bất kỳ mô-đun nhập khẩu.
Tôi chưa bao giờ thấy các đường dẫn bị gạch chéo kép, chúng có tồn tại không? Tính năng tích hợp của mô-đun python os
không thành công cho những người đó. Tất cả những người khác làm việc, cũng là cảnh báo do bạn đưa ra với os.path.normpath()
:
paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c', 'a/./b/c', 'a\b/c']
for path in paths:
os.path.basename(os.path.normpath(path))
Dấu phân cách Windows có thể ở tên tệp Unix hoặc Windows Path. Dấu tách Unix chỉ có thể tồn tại trong đường dẫn Unix. Sự hiện diện của dấu phân cách Unix biểu thị đường dẫn không phải của Windows.
Sau đây sẽ loại bỏ (cắt dấu phân cách) bằng dấu phân cách cụ thể của hệ điều hành, sau đó phân tách và trả về giá trị ngoài cùng bên phải. Nó xấu, nhưng đơn giản dựa trên giả định ở trên. Nếu giả định không chính xác, vui lòng cập nhật và tôi sẽ cập nhật phản hồi này để phù hợp với các điều kiện chính xác hơn.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
mã mẫu:
b = ['a/b/c/','a/b/c','\\a\\b\\c','\\a\\b\\c\\','a\\b\\c','a/b/../../a/b/c/','a/b/../../a/b/c']
for a in b:
print (a, a.rstrip("\\" if a.count("/") == 0 else '/').split("\\" if a.count("/") == 0 else '/')[-1])
Để hoàn thiện hơn, đây là pathlib
giải pháp cho python 3.2+:
>>> from pathlib import PureWindowsPath
>>> paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
>>> [PureWindowsPath(path).name for path in paths]
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Điều này hoạt động trên cả Windows và Linux.
Trong cả Python 2 và 3, sử dụng mô-đun pathlib2 :
import posixpath # to generate unix paths
from pathlib2 import PurePath, PureWindowsPath, PurePosixPath
def path2unix(path, nojoin=True, fromwinpath=False):
"""From a path given in any format, converts to posix path format
fromwinpath=True forces the input path to be recognized as a Windows path (useful on Unix machines to unit test Windows paths)"""
if not path:
return path
if fromwinpath:
pathparts = list(PureWindowsPath(path).parts)
else:
pathparts = list(PurePath(path).parts)
if nojoin:
return pathparts
else:
return posixpath.join(*pathparts)
Sử dụng:
In [9]: path2unix('lala/lolo/haha.dat')
Out[9]: ['lala', 'lolo', 'haha.dat']
In [10]: path2unix(r'C:\lala/lolo/haha.dat')
Out[10]: ['C:\\', 'lala', 'lolo', 'haha.dat']
In [11]: path2unix(r'C:\lala/lolo/haha.dat') # works even with malformatted cases mixing both Windows and Linux path separators
Out[11]: ['C:\\', 'lala', 'lolo', 'haha.dat']
Với testcase của bạn:
In [12]: testcase = paths = ['a/b/c/', 'a/b/c', '\\a\\b\\c', '\\a\\b\\c\\', 'a\\b\\c',
...: ... 'a/b/../../a/b/c/', 'a/b/../../a/b/c']
In [14]: for t in testcase:
...: print(path2unix(t)[-1])
...:
...:
c
c
c
c
c
c
c
Ý tưởng ở đây là chuyển đổi tất cả các đường dẫn thành biểu diễn bên trong thống nhất pathlib2
, với các bộ giải mã khác nhau tùy thuộc vào nền tảng. May mắn thay, pathlib2
bao gồm một bộ giải mã chung được gọi là PurePath
sẽ hoạt động trên bất kỳ đường dẫn nào. Trong trường hợp điều này không hoạt động, bạn có thể buộc nhận dạng đường dẫn windows bằng cách sử dụng fromwinpath=True
. Điều này sẽ chia chuỗi đầu vào thành các phần, cái cuối cùng là chiếc lá bạn đang tìm kiếm, do đó path2unix(t)[-1]
.
Nếu đối số nojoin=False
, đường dẫn sẽ được nối lại, do đó đầu ra chỉ đơn giản là chuỗi đầu vào được chuyển đổi sang định dạng Unix, có thể hữu ích để so sánh các đường dẫn phụ trên các nền tảng.
os.path
chỉ cần tảintpath
mô-đun bên trong. Sử dụng mô-đun này, có thể xử lý các'\\'
dấu tách đường dẫn ngay cả trên các máy Linux. Đối với Linux,posixpath
mô-đun (resp.os.path
) Sẽ đơn giản hóa các hoạt động đường dẫn để chỉ cho phép các'/'
dấu tách kiểu posix .