Yanıtlar:
os.path.split
Veya os.path.basename
başkalarının önerdiği gibi kullanmak her durumda işe yaramaz: komut dosyasını Linux'ta çalıştırıyorsanız ve klasik bir pencere stili yolunu işlemeye çalışırsanız başarısız olur.
Windows yolları, yol ayırıcı olarak ters eğik çizgi veya ileri eğik çizgi kullanabilir. Bu nedenle, ntpath
modül (pencerelerde çalışırken os.path'e eşdeğerdir ) tüm platformlardaki tüm (1) yollar için çalışır.
import ntpath
ntpath.basename("a/b/c")
Tabii ki, dosya bir eğik çizgi ile biterse, taban adı boş olacaktır, bu yüzden onunla başa çıkmak için kendi işlevinizi yapın:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Doğrulama:
>>> 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) Bir uyarı var: Linux dosya adları ters eğik çizgiler içerebilir . Yani linux üzerinde, r'a/b\c'
her zaman dosyaya atıfta b\c
içinde a
Windows üzerinde, her zaman ifade eder iken, klasördeki c
dosya b
içinde alt klasör a
klasöründe. Bu nedenle, hem ileri hem de geri eğik çizgiler bir yolda kullanıldığında, doğru bir şekilde yorumlayabilmek için ilişkili platformu bilmeniz gerekir . Uygulamada, ters eğik çizgiler Linux dosya adlarında nadiren kullanıldığından, bunun bir pencere yolu olduğunu varsaymak genellikle güvenlidir, ancak kod yazarken bunu göz önünde bulundurun, böylece yanlışlıkla güvenlik delikleri oluşturmazsınız.
r'C:\path\to\file.txt'
bir Linux makinesinde Windows stil yollarını (örn. ) Ayrıştırmanız gerektiğinde, ntpath modülünü kullanmanız gerekir. Aksi takdirde, os.path işlevini kullanabilirsiniz. Bunun nedeni, Linux sistemlerinin normalde dosya adlarında (yanıtta açıklandığı gibi) ters eğik çizgi karakterlerinin kullanılmasına izin vermesidir.
os.path.basename(os.path.normpath(path))
mi?
Aslında, tam olarak istediğinizi döndüren bir işlev var
import os
print(os.path.basename(your_path))
os.path.basename(your_path)
Bu işe yaradı! : Senaryonun yolunu istedi os.path.dirname(os.path.realpath(__file__))
ve komut dosyası adını: os.path.basename(os.path.realpath(__file__))
. Teşekkürler!
'C:\\temp\\bla.txt'
bunun yerine elde edersiniz .
os.path.split , aradığınız işlevdir
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')
kuyruk istediğiniz şeydir, dosya adı.
Bkz piton os modülü belgeler ayrıntı
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
Örneğinizde, geri dönmek için sağdan sağa eğik çizgi yapmanız gerekir c
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
İkinci seviye:
>>> os.path.filename(os.path.dirname(path))
'b'
güncelleme: Bence lazyr
doğru cevabı verdi. Kodum, unix sistemlerindeki windows benzeri yollarla ve Windows sistemindeki unix benzeri yollarla karşılaştırıldığında işe yaramaz.
r"a\b\c"
linux veya "a/b/c"
pencerelerde çalışmaz .
os.path.basename(path)
yalnızca çalışacak os.path.isfile(path)
olan True
. Bu nedenle path = 'a/b/c/'
geçerli bir dosya adı değil ...
os.path.basename("a/b/c/")
geri döner ""
.
lazyr
Haklısın! Bunu düşünmemiştim. Sadece yapmak güvenli olur path = path.replace('\\', '/')
mu?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
bu dönecektir: paint.exe
yolunuz veya işletim sisteminizle ilgili split işlevinin sep değerini değiştirin.
fname = str(path).split('/')[-1]
Dosya yolunuz "/" ile bitmemişse ve dizinler "/" ile ayrılmışsa, aşağıdaki kodu kullanın. Bildiğimiz gibi genel olarak yol "/" ile bitmiyor.
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Ancak, URL'ler gibi "/" ile biten bazı durumlarda aşağıdaki kodu kullanın
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
ancak yolunuz genellikle Windows yollarında bulduğunuz "\" ile belirtildiğinde aşağıdaki kodları kullanabilirsiniz
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]))
İşletim sistemi türünü kontrol ederek ve sonucu döndürerek her ikisini de tek bir işlevde birleştirebilirsiniz.
Bu standart kitaplık ile linux ve pencereler için de çalışıyor
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]
Sonuçlar:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
İşte herhangi bir işletim sistemindeki herhangi bir işletim sistemi yolu ile çalışıyor gibi görünen normal regex çözümü.
Başka bir modüle gerek yoktur ve ön işleme gerek yoktur:
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']
Güncelleme:
Yalnızca istiyorsanız potansiyel dosya mevcut (yani eğer /a/b/
bir dir ve böyledir c:\windows\
), için regex'i değiştirin: r'[^\\/]+(?![\\/])$'
. "Regex meydan okudu" için, bu, bir tür eğik çizgi için pozitif ileriye doğru ileriye bakmayı negatif ileriye doğru bir ileriye çevirir ve adı geçen eğik çizgi ile biten yol adlarının yol adındaki son alt dizin yerine hiçbir şey döndürmemesine neden olur . Elbette, potansiyel dosya adının aslında bir dosyaya atıfta bulunduğunu ve bunun için kullanılması os.path.is_dir()
ya os.path.is_file()
da kullanılması gerekeceğini garanti etmez .
Bu şu şekilde eşleşecektir:
/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
Normal ifade burada test edilebilir .
Belki de sadece benim yeni bir çözüm önemli olmadan bazı yeni (geçici dosyaları oluşturmak için geçici dosya göz önünde bulundurun: D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Değerleri almak abc.name
şöyle bir dize olacaktır: '/tmp/tmpks5oksk7'
Böylece /
bir boşluk ile değiştirin .replace("/", " ")
ve sonra arayın split()
. Bu bir liste döndürecek ve listenin son öğesini[-1]
Herhangi bir modülün ithal edilmesine gerek yoktur.
Daha önce çift ters eğik çizgiler görmedim, bunlar var mı? Python modülünün yerleşik özelliği bunlar os
için başarısız olur. Tüm diğerleri, ayrıca sizin tarafınızdan verilen uyarı ile çalışır 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))
Windows ayırıcı bir Unix dosya adında veya Windows Yolunda olabilir. Unix ayırıcısı yalnızca Unix yolunda bulunabilir. Unix ayırıcısının varlığı, Windows olmayan bir yolu gösterir.
Aşağıdakiler, OS'ye özgü ayırıcı tarafından sıyrılır (kesme iz ayırıcısı), daha sonra bölünür ve en sağdaki değeri döndürür. Yukarıdaki varsayımlara dayanarak çirkin ama basit. Varsayım yanlışsa, lütfen güncelleyin; bu yanıtı daha doğru koşullara uyacak şekilde güncelleyeceğim.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
basit kod:
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])
pathlib
Tamlık uğruna, python 3.2+ için çözüm:
>>> 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']
Bu hem Windows hem de Linux üzerinde çalışır.
Python 2 ve 3'te pathlib2 modülünü kullanarak :
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)
Kullanımı:
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']
Test çantanızla:
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
Buradaki fikir, tüm yolları pathlib2
platforma bağlı olarak farklı kod çözücülerle birleştirilmiş dahili temsile dönüştürmektir . Neyse ki, herhangi bir yolda çalışması gereken pathlib2
genel bir kod çözücü içerir PurePath
. Bu işe yaramazsa, kullanarak Windows yolunu tanımayı zorlayabilirsinizfromwinpath=True
. Bu, giriş dizesini parçalara böler, sonuncusu aradığınız yaprak, dolayısıyla path2unix(t)[-1]
.
Bağımsız değişken nojoin=False
ise, yol geri birleştirilir, böylece çıktı yalnızca platformlar arasındaki alt yolları karşılaştırmak için yararlı olabilecek bir Unix biçimine dönüştürülen giriş dizesidir.
os.path
yüklerntpath
. Bu modülü kullanarak'\\'
, Linux makinelerde bile yol ayırıcıları işlemek mümkündür . Linux içinposixpath
modül (sırasıylaos.path
), yalnızca posix stil'/'
ayırıcılarına izin vermek için yol işlemlerini basitleştirecektir .