Antworten:
Die Verwendung von os.path.split
oder os.path.basename
wie von anderen vorgeschlagen, funktioniert nicht in allen Fällen: Wenn Sie das Skript unter Linux ausführen und versuchen, einen klassischen Windows-Pfad zu verarbeiten, schlägt dies fehl.
Windows-Pfade können entweder einen Schrägstrich oder einen Schrägstrich als Pfadtrennzeichen verwenden. Daher ntpath
funktioniert das Modul (das unter Windows os.path entspricht) für alle (1) Pfade auf allen Plattformen.
import ntpath
ntpath.basename("a/b/c")
Wenn die Datei mit einem Schrägstrich endet, ist der Basisname natürlich leer. Erstellen Sie also Ihre eigene Funktion, um damit umzugehen:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Nachprüfung:
>>> 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) Es gibt eine Einschränkung: Linux-Dateinamen können Backslashes enthalten . Unter Linux wird also r'a/b\c'
immer auf die Datei b\c
im a
Ordner verwiesen, während unter Windows immer auf die c
Datei im b
Unterordner des a
Ordners verwiesen wird. Also , wenn beide vorwärts und rückwärts Schrägstriche in einem Pfad verwendet werden, Sie müssen die zugehörige Plattform kennen, um es richtig zu interpretieren. In der Praxis ist es normalerweise sicher anzunehmen, dass es sich um einen Windows-Pfad handelt, da Backslashes in Linux-Dateinamen selten verwendet werden. Beachten Sie dies jedoch beim Codieren, damit keine versehentlichen Sicherheitslücken entstehen.
r'C:\path\to\file.txt'
) auf einem Linux-Computer analysieren müssen , müssen Sie das ntpath-Modul verwenden. Andernfalls können Sie die Funktionen von os.path verwenden. Dies liegt daran, dass Linux-Systeme normalerweise die Verwendung der Backslash-Zeichen in Dateinamen zulassen (wie in der Antwort erläutert).
os.path.basename(os.path.normpath(path))
?
Tatsächlich gibt es eine Funktion , die genau das zurückgibt, was Sie wollen
import os
print(os.path.basename(your_path))
os.path.basename(your_path)
Das hat funktioniert! Ich wollte Skriptpfad: os.path.dirname(os.path.realpath(__file__))
und Skriptname : os.path.basename(os.path.realpath(__file__))
. Vielen Dank!
'C:\\temp\\bla.txt'
stattdessen bekommen .
os.path.split ist die Funktion, nach der Sie suchen
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')
Schwanz ist was du willst, der Dateiname.
Weitere Informationen finden Sie in den Dokumenten zum Python OS-Modul
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
In Ihrem Beispiel müssen Sie auch den Schrägstrich von rechts auf der rechten Seite entfernen, um zurückzukehren c
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Zweites Level:
>>> os.path.filename(os.path.dirname(path))
'b'
Update: Ich denke, lazyr
hat die richtige Antwort geliefert. Mein Code funktioniert nicht mit Windows-ähnlichen Pfaden auf Unix-Systemen und umgekehrt mit Unix-ähnlichen Pfaden auf Windows-Systemen.
r"a\b\c"
unter Linux noch "a/b/c"
unter Windows.
os.path.basename(path)
funktioniert natürlich nur wenn es os.path.isfile(path)
ist True
. Daher path = 'a/b/c/'
ist überhaupt kein gültiger Dateiname ...
os.path.basename("a/b/c/")
kehrt ""
wegen des abschließenden Schrägstrichs zurück.
lazyr
Sie haben Recht! Daran habe ich nicht gedacht. Wäre es sicher, es einfach zu tun path = path.replace('\\', '/')
?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
Dies wird zurückgeben: paint.exe
Ändern Sie den sep-Wert der Split-Funktion in Bezug auf Ihren Pfad oder Ihr Betriebssystem.
fname = str(path).split('/')[-1]
Wenn Ihr Dateipfad nicht mit "/" und durch "/" getrennten Verzeichnissen endet, verwenden Sie den folgenden Code. Wie wir allgemein wissen, endet der Pfad nicht mit "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
In einigen Fällen, in denen URLs mit "/" enden, wird der folgende Code verwendet
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
Wenn Ihr Pfad jedoch durch "\" getrennt ist, was Sie normalerweise in Windows-Pfaden finden, können Sie die folgenden Codes verwenden
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]))
Sie können beide zu einer Funktion kombinieren, indem Sie den Betriebssystemtyp überprüfen und das Ergebnis zurückgeben.
Dies funktioniert auch für Linux und Windows mit Standardbibliothek
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]
Ergebnisse:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Hier ist eine reine Regex-Lösung, die mit jedem Betriebssystempfad auf jedem Betriebssystem zu funktionieren scheint.
Es wird kein anderes Modul benötigt und es ist auch keine Vorverarbeitung erforderlich:
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']
Aktualisieren:
Wenn Sie nur einen potenziellen Dateinamen wünschen , falls vorhanden (dh ein Verzeichnis /a/b/
und so ist c:\windows\
), ändern Sie den regulären Ausdruck in : r'[^\\/]+(?![\\/])$'
. Für den "herausgeforderten regulären Ausdruck" ändert dies den positiven Forward-Lookahead für eine Art Schrägstrich in einen negativen Forward-Lookahead, wodurch Pfadnamen, die mit diesem Schrägstrich enden, nichts anstelle des letzten Unterverzeichnisses im Pfadnamen zurückgeben. Natürlich gibt es keine Garantie dafür, dass sich der potenzielle Dateiname tatsächlich auf eine Datei bezieht und dafür verwendet werden müsste os.path.is_dir()
oder os.path.is_file()
müsste.
Dies wird wie folgt übereinstimmen:
/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
Der Regex kann hier getestet werden .
Vielleicht nur meine All-in-One-Lösung ohne wichtige neue (siehe Tempfile zum Erstellen temporärer Dateien: D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Das Erhalten der Werte von abc.name
wird eine Zeichenfolge wie die folgende sein: '/tmp/tmpks5oksk7'
Also kann ich die /
durch ein Leerzeichen ersetzen .replace("/", " ")
und dann aufrufen split()
. Das gibt eine Liste zurück und ich bekomme das letzte Element der Liste mit[-1]
Es muss kein Modul importiert werden.
Ich habe noch nie Pfade mit doppeltem Schrägstrich gesehen. Gibt es sie? Die integrierte Funktion des Python-Moduls os
schlägt für diese fehl. Alle anderen arbeiten, auch die von Ihnen gegebene Einschränkung mit 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))
Das Windows-Trennzeichen kann sich in einem Unix-Dateinamen oder einem Windows-Pfad befinden. Das Unix-Trennzeichen kann nur im Unix-Pfad vorhanden sein. Das Vorhandensein eines Unix-Trennzeichens weist auf einen Nicht-Windows-Pfad hin.
Im Folgenden wird das hintere Trennzeichen durch das betriebssystemspezifische Trennzeichen entfernt (abgeschnitten), dann geteilt und der Wert ganz rechts zurückgegeben. Es ist hässlich, aber einfach, basierend auf der obigen Annahme. Wenn die Annahme falsch ist, aktualisieren Sie bitte und ich werde diese Antwort aktualisieren, um den genaueren Bedingungen zu entsprechen.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
Beispielcode:
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])
Der Vollständigkeit halber ist hier die pathlib
Lösung für 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']
Dies funktioniert sowohl unter Windows als auch unter Linux.
Verwenden Sie in Python 2 und 3 das 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)
Verwendungszweck:
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']
Mit Ihrem Testfall:
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
Hier geht es darum, alle Pfade in die einheitliche interne Darstellung von zu konvertieren pathlib2
, wobei je nach Plattform unterschiedliche Decoder vorhanden sind. Glücklicherweise pathlib2
enthält ein generischer Decoder namens PurePath
, der auf jedem Pfad funktionieren sollte. Falls dies nicht funktioniert, können Sie die Erkennung des Windows-Pfads mithilfe von erzwingen fromwinpath=True
. Dadurch wird die Eingabezeichenfolge in Teile aufgeteilt. Das letzte ist das gesuchte Blatt, daher daspath2unix(t)[-1]
.
Wenn das Argument verwendet wird nojoin=False
, wird der Pfad wieder verknüpft, sodass die Ausgabe einfach die in ein Unix-Format konvertierte Eingabezeichenfolge ist. Dies kann hilfreich sein, um Unterpfade plattformübergreifend zu vergleichen.
os.path
Lädt dasntpath
Modul unter Windows nur intern. Mit diesem Modul ist es möglich, die'\\'
Pfadtrennzeichen auch auf Linux-Computern zu handhaben . Unter Linux vereinfacht dasposixpath
Modul (bzw.os.path
) die Pfadoperationen, um nur'/'
Trennzeichen im Posix-Stil zuzulassen .