Yang Python library yang dapat saya gunakan untuk mengekstrak file dari jalan, tidak peduli apa sistem operasi atau format path bisa?
Sebagai contoh, saya'd seperti semua jalan untuk kembali padaku c
:
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
Menggunakan os.jalan.membagi
atau os.jalan.basename
seperti yang orang lain sarankan won't bekerja dalam semua kasus: jika anda're menjalankan script pada Linux dan mencoba untuk proses klasik windows-style jalan, itu akan gagal.
Windows jalan dapat menggunakan backslash atau garis miring sebagai pemisah jalan. Oleh karena itu, ntpath
modul (yang sama dengan os.jalan ketika berjalan pada windows) akan bekerja untuk semua(1) jalan di semua platform.
import ntpath
ntpath.basename("a/b/c")
Tentu saja, jika file yang diakhiri dengan slash, basename akan kosong, sehingga membuat fungsi sendiri untuk menghadapinya:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Verifikasi:
>>> 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) Ada's satu peringatan: Linux nama file mungkin berisi garis miring terbalik. Jadi di linux, r'a/b\c'
selalu mengacu pada file b\c
di a
folder, sedangkan pada Windows, selalu mengacu pada c
file b
subfolder dari a
folder. Jadi, ketika keduanya ke depan dan ke belakang garis miring digunakan di jalan, yang anda butuhkan ** untuk mengetahui terkait platform untuk dapat menafsirkan dengan benar. Dalam prakteknya's biasanya aman untuk mengasumsikan itu's windows path sejak garis miring terbalik jarang digunakan di Linux nama file, tapi menjaga ini dalam pikiran ketika anda kode sehingga anda don't menciptakan disengaja lubang keamanan.
os.jalan.split adalah fungsi yang anda cari
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
Dalam contoh anda, anda juga akan perlu untuk strip miring dari kanan sisi kanan untuk kembali c
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Tingkat kedua:
>>> os.path.filename(os.path.dirname(path))
'b'
update: saya pikir lazyr
telah memberikan jawaban yang tepat. Kode saya tidak akan bekerja dengan windows-seperti jalur pada sistem unix dan wakil dibandingkan dengan unix-like jalur pada sistem windows.
Ini bekerja untuk linux dan windows juga dengan standar perpustakaan
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]
Hasil:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Jika anda path file tidak berakhir dengan "/" dan direktori dipisahkan oleh "/" kemudian gunakan kode berikut. Seperti yang kita tahu pada umumnya jalan doesn't end dengan "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Namun dalam beberapa kasus seperti Url yang diakhiri dengan "/" kemudian gunakan kode berikut
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
tapi ketika anda jalan sperated oleh "\" yang biasanya anda temukan di windows jalan maka anda dapat menggunakan kode berikut
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]))
Anda dapat menggabungkan keduanya menjadi satu fungsi dengan memeriksa jenis OS dan mengembalikan hasil.
Berikut ini's regex-satunya solusi, yang tampaknya untuk bekerja dengan OS jalan di OS apa saja.
Tidak ada modul lain yang dibutuhkan, dan tidak ada preprocessing yang dibutuhkan berupa :
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']
Update:
Jika anda hanya ingin potensi nama file, jika saat ini (yaitu, /a/b/
adalah dir dan jadi lebih c:\windows\
), perubahan ekspresi reguler: r'[^\\/]+(?![\\/])$'
. Untuk "regex menantang," ini perubahan positif ke depan lookahead untuk semacam slash negatif ke depan lookahead, menyebabkan nama path yang berakhir dengan kata miring untuk kembali apa-apa bukan yang terakhir sub-direktori di path. Tentu saja tidak ada jaminan bahwa potensi nama file sebenarnya mengacu pada sebuah file dan untuk itu os.jalan.is_dir()
atau os.jalan.is_file()
akan perlu untuk bekerja.
Ini akan cocok sebagai berikut:
/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 dapat diuji di sini.
python impor os file_location = '/srv/volume1/data/eds/eds_report.csv' file_name = os.jalan.basename(file_location ) #eds_report.csv lokasi = os.jalan.dirname(file_location ) #/srv/volume1/data/eds
Saya belum pernah melihat ganda-backslashed jalan, apakah mereka ada? Built-in fitur dari modul python os
gagal untuk mereka. Semua orang lain yang bekerja, juga peringatan yang diberikan oleh anda dengan os.jalan.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))
Windows pemisah bisa di Unix nama file atau Path Windows. Unix pemisah yang hanya bisa ada di Unix jalan. Kehadiran Unix pemisah menunjukkan non-Windows path.
Berikut ini akan strip (cut tertinggal separator) dengan OS tertentu pemisah, kemudian berpisah dan kembali paling kanan nilai. It's jelek, tapi sederhana didasarkan pada asumsi di atas. Jika asumsi ini benar, silahkan update dan saya akan update ini tanggapan untuk mencocokkan kondisi yang lebih akurat.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
contoh kode:
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])
Mungkin hanya saya, semua dalam satu solusi tanpa penting beberapa yang baru(hal tempfile untuk membuat file-file sementara :D )
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Mendapatkan nilai-nilai dari abc.nama
akan menjadi sebuah string seperti ini: '/tmp/tmpks5oksk7'
Jadi saya bisa mengganti /
ruang .mengganti("/", " ")
dan kemudian memanggil split()
. Itu akan kembali daftar dan saya mendapatkan
elemen terakhir dari list dengan [-1]
Tidak perlu untuk mendapatkan semua modul yang diimpor.
Untuk kelengkapan sake, di sini adalah pathlib
solusi untuk 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']
Ini bekerja pada Windows dan Linux.
Di kedua Python 2 dan 3, menggunakan modul 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)
Penggunaan:
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']
Dengan kasus tes:
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
Idenya di sini adalah untuk mengkonversi semua jalan ke terpadu representasi internal dari pathlib2
, berbeda dengan decoder tergantung pada platform. Untungnya, pathlib2
mencakup generik decoder yang disebut PurePath
yang harus bekerja pada setiap jalur. Dalam kasus ini tidak bekerja, anda dapat memaksa pengakuan dari jalan windows menggunakan fromwinpath=True
. Ini akan membagi string menjadi beberapa bagian, yang terakhir adalah daun yang anda cari, maka path2unix(t)[-1]
.
Jika argumen nojoin=False
, jalan akan bergabung kembali, sehingga output hanya input string dikonversi ke format Unix, yang dapat berguna untuk membandingkan subpath di seluruh platform.