Care Python library pot folosi pentru a extrage nume de fișiere de trasee, indiferent de ce sistem de operare sau calea de format ar putea fi?
De exemplu, am'd ca toate aceste căi pentru a-mi reveni "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
Folosind os.calea.split " sau " os.calea.basename
ca alții sugerează câștigat't de lucru în toate cazurile: daca're rulează script-ul de pe Linux și încercarea de a procesa un clasic windows-stil de drum, acesta va eșua.
Windows căi pot folosi fie backslash sau slash ca o cale de separare. Prin urmare, ntpath
module (care este echivalent cu sistemul de operare.calea atunci când rulează pe windows), va lucra pentru toate(1) căi pe toate platformele.
import ntpath
ntpath.basename("a/b/c")
Desigur, dacă fișierul se termină cu un slash, basename va fi gol, deci face propriile funcția de a face cu ea:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Verificare:
>>> 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)'s o precizare: Linux nume de fișiere poate conține backslash-uri. Deci pe linux, r'a/b\c' întotdeauna se referă la fișierul b\c
în o
dosar, în timp ce pe Windows, acesta se referă întotdeauna la " c "fișier în" b "subfolder al" un " folder. Deci, atunci când atât înainte și înapoi slash-uri sunt folosite într-o cale, ai trebui să cunoască asociate platformă pentru a fi capabil să-l interpreteze corect. În practică, se's, de obicei, în condiții de siguranță să-și asume o's un windows cale de backslash-uri sunt rareori utilizate în Linux nume de fișiere, dar păstrați acest lucru în minte atunci când ai cod, astfel încât să don't crea accidentale gauri de securitate.
os.calea.split este funcția sunteți în căutarea pentru
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
În exemplul de asemenea, va trebui să se dezbrace slash de la dreapta la dreapta pentru a reveni "c":
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Al doilea nivel:
>>> os.path.filename(os.path.dirname(path))
'b'
update: cred că lazyr` a oferit răspunsul corect. Codul meu nu va funcționa cu windows-cum ar fi căile pe sistemele unix și vice comparativ cu unix-cum ar fi căile pe sistemul de operare windows.
Acest lucru este de lucru pentru linux și windows, precum și cu biblioteca standard
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]
Rezultate:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Dacă calea de fișier nu s-a încheiat cu "/" și directoare separate prin "/" apoi, utilizați următorul cod. După cum știm, în general, calea nu't end cu "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Dar, în unele cazuri cum ar fi Url-end cu "/" apoi, utilizați următorul cod
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
dar când calea ta despartiti de "\" care, în general, găsit în windows căi, atunci puteți folosi următoarele coduri
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]))
Puteți combina ambele într-o funcție de verificare tipul sistemului de OPERARE și întoarce rezultatul.
Aici's un regex-singura soluție, care pare să funcționeze cu orice sistem de OPERARE calea pe orice sistem de OPERARE.
Nici un alt modul este necesar, și nu de preprocesare este nevoie de :
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:
Dacă doriți doar un potențial filename, dacă este prezent (de exemplu, /a/b/
este un dir și așa este c:\windows`), schimba regex pentru a: r'[^\\/]+(?![\\/])$'
. Pentru "regex contestat," asta schimbări pozitive față posibilitate pentru un fel de slash la un negativ înainte lookahead, provocând cai de acces care se termina cu a spus slash pentru a reveni nimic în loc de ultima sub-director în cale. Desigur, nu există nici o garanție că potențial filename, de fapt se referă la un fișier și pentru că `os.calea.is_dir () " sau " os.calea.is_file () ar trebui să fie angajați.
Acest lucru se va potrivi după cum urmează:
/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 poate fi testat aici.
python import os file_location = '/srv/volume1/date/eds/eds_report.csv' nume_fișier = os.calea.basename(file_location ) #eds_report.csv locație = os.calea.dirname(file_location ) #/srv/volume1/date/eds
Nu am văzut niciodată dublu-backslashed căi, sunt existente? Built-in funcție de modul python os
nu pentru cei. Toate celelalte funcționează, de asemenea, avertismentul dat de tine cu os.calea.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 separator poate fi într-un fisier Unix sau Windows Cale. Unix separator poate exista doar în Unix calea. Prezența unui Unix separator indică un non-Windows cale.
Următoarele va bandă (se taie la final separator) de către sistemul de OPERARE specifice separator, apoi împărțit și a reveni la valoarea din dreapta. L's urât, dar simplu bazat pe presupunerea de mai sus. În cazul în care ipoteza este incorectă, vă rugăm să actualizați și voi actualiza acest răspuns pentru a se potrivi condiții mai precise.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
mostre de cod:
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])
Poate doar într-o singură soluție fără importantă unele noi(sens tempfile pentru crearea de fișiere temporare :D )
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Obtinerea de valori de abc.numele va fi un șir de genul asta: '/tmp/tmpks5oksk7'
Deci nu pot înlocui /
cu un spațiu .înlocui("/", " ") și apoi apel
split(). Care va returna o listă și am ultimul element al listei cu
[-1]`
Nu este nevoie pentru a obține orice module importate.
Pentru completitudine dumnezeu, aici este `pathlib soluție pentru 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']
Acesta funcționează atât pe Windows și Linux.
În ambele Python 2 și 3, folosind modulul 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)
Utilizare:
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']
Cu testcase:
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
Ideea aici este de a converti toate căile în unified reprezentarea internă a pathlib2
, cu decodoare diferite, în funcție de platformă. Din fericire, pathlib2 include un generic decodor numit
PurePath că ar trebui să funcționeze pe orice cale. În cazul în care acest lucru nu funcționează, puteți forța recunoașterea windows cale folosind fromwinpath=True
. Acest lucru va împărți șirul de intrare în părți, ultima este frunza sunteți în căutarea pentru, prin urmare path2unix(t)[-1]
.
Dacă argumentul nojoin=False
, calea va fi alăturat înapoi, astfel că producția este pur și simplu șir de intrare convertit la un format Unix, care pot fi utile pentru a compara subpaths pe platforme.