Respostas:
Usar os.path.split
ou os.path.basename
como outros sugerem não funcionará em todos os casos: se você estiver executando o script no Linux e tentar processar um caminho clássico no estilo Windows, ele falhará.
Os caminhos do Windows podem usar barra invertida ou barra invertida como separador de caminho. Portanto, o ntpath
módulo (que é equivalente ao os.path ao executar no Windows) funcionará para todos os (1) caminhos em todas as plataformas.
import ntpath
ntpath.basename("a/b/c")
Obviamente, se o arquivo terminar com uma barra, o nome da base ficará vazio; portanto, faça sua própria função para lidar com isso:
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
Verificação:
>>> 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) Há uma ressalva: os nomes de arquivos do Linux podem conter barras invertidas . Portanto, no linux, r'a/b\c'
sempre se refere ao arquivo b\c
na a
pasta, enquanto no Windows, sempre se refere ao c
arquivo na b
subpasta da a
pasta. Portanto, quando ambas as barras são usadas em um caminho, você precisa conhecer a plataforma associada para poder interpretá-la corretamente. Na prática, geralmente é seguro assumir que é um caminho do Windows, já que as barras invertidas raramente são usadas nos nomes de arquivos do Linux, mas lembre-se disso quando você codificar para não criar falhas acidentais na segurança.
r'C:\path\to\file.txt'
) em uma máquina Linux, precisará usar o módulo ntpath. Caso contrário, você pode usar as funções do os.path. Isso ocorre porque os sistemas Linux normalmente permitem o uso dos caracteres de barra invertida nos nomes de arquivos (conforme explicado na resposta).
os.path.basename(os.path.normpath(path))
?
Na verdade, há uma função que retorna exatamente o que você deseja
import os
print(os.path.basename(your_path))
os.path.basename(your_path)
Isso funcionou! Eu queria caminho do script: os.path.dirname(os.path.realpath(__file__))
eo nome do script: os.path.basename(os.path.realpath(__file__))
. Obrigado!
'C:\\temp\\bla.txt'
.
os.path.split é a função que você está procurando
head, tail = os.path.split("/tmp/d/a.dat")
>>> print(tail)
a.dat
>>> print(head)
/tmp/d
Em python 3
>>> from pathlib import Path
>>> Path("/tmp/d/a.dat").name
'a.dat'
import os
head, tail = os.path.split('path/to/file.exe')
cauda é o que você quer, o nome do arquivo.
Veja os documentos do módulo OS do python para obter detalhes
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
No seu exemplo, você também precisará remover a barra do lado direito para retornar c
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
Segundo nível:
>>> os.path.filename(os.path.dirname(path))
'b'
atualização: acho lazyr
que forneceu a resposta certa. Meu código não funcionará com caminhos semelhantes a janelas em sistemas unix e vice-versa com caminhos semelhantes a unix em sistemas Windows.
r"a\b\c"
no linux, nem "a/b/c"
no windows.
os.path.basename(path)
só funcionará se os.path.isfile(path)
for True
. Portanto, path = 'a/b/c/'
não é um nome de arquivo válido ...
os.path.basename("a/b/c/")
retorna ""
devido à barra final.
lazyr
você está certo! Eu não pensei sobre isso. Seria seguro apenas fazer path = path.replace('\\', '/')
?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
isso retornará: paint.exe
altere o valor sep da função de divisão em relação ao seu caminho ou SO.
fname = str(path).split('/')[-1]
Se o caminho do arquivo não terminar com "/" e os diretórios separados por "/", use o código a seguir. Como sabemos, geralmente o caminho não termina com "/".
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
Mas, em alguns casos, como os URLs terminam com "/", use o seguinte código
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
mas quando seu caminho é marcado por "\", que você geralmente encontra nos caminhos do Windows, pode usar os seguintes códigos
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]))
Você pode combinar as duas em uma função, verificando o tipo de SO e retornando o resultado.
Isso funciona para linux e windows, bem como para a biblioteca padrão
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]
Resultados:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
Aqui está uma solução somente regex, que parece funcionar com qualquer caminho do sistema operacional em qualquer sistema operacional.
Nenhum outro módulo é necessário e também não é necessário pré-processamento:
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']
Atualizar:
Se você quiser apenas uma potencial filename, se presente (ou seja, /a/b/
é um dir e assim é c:\windows\
), altere o regex para: r'[^\\/]+(?![\\/])$'
. Para o "regex contestado", isso altera a aparência positiva positiva de algum tipo de barra para uma negativa negativa, fazendo com que os nomes de caminho que terminam com a barra não retornem nada, em vez do último subdiretório do nome do caminho. Obviamente, não há garantia de que o nome do arquivo em potencial se refira a um arquivo e, para isso, os.path.is_dir()
ou os.path.is_file()
precise ser empregado.
Isso corresponderá da seguinte forma:
/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
O regex pode ser testado aqui .
Talvez apenas a minha solução completa sem importantes novidades (considere o tempfile para criar arquivos temporários: D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
Obter os valores de abc.name
será uma sequência como esta: '/tmp/tmpks5oksk7'
Para que eu possa substituir o /
por um espaço .replace("/", " ")
e depois chamar split()
. Isso retornará uma lista e eu recebo o último elemento da lista com[-1]
Não é necessário importar nenhum módulo.
Nunca vi caminhos com barra invertida dupla, eles existem? O recurso interno do módulo python os
falha para eles. Todos os outros funcionam, também a ressalva dada por você com 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))
O separador do Windows pode estar em um nome de arquivo Unix ou em Caminho do Windows. O separador Unix pode existir apenas no caminho Unix. A presença de um separador Unix indica um caminho que não é do Windows.
A seguir, o separador específico do sistema operacional será separado (separador de corte cortado), depois será dividido e retornará o valor mais à direita. É feio, mas simples, com base no pressuposto acima. Se a suposição estiver incorreta, atualize e eu atualizarei esta resposta para atender às condições mais precisas.
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
Código de amostra:
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])
Para completar, aqui está a pathlib
solução para o 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']
Isso funciona no Windows e Linux.
No Python 2 e 3, usando o módulo 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)
Uso:
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']
Com sua caixa de teste:
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
A idéia aqui é converter todos os caminhos na representação interna unificada de pathlib2
, com diferentes decodificadores, dependendo da plataforma. Felizmente, pathlib2
inclui um decodificador genérico chamado PurePath
que deve funcionar em qualquer caminho. Caso isso não funcione, você pode forçar o reconhecimento do caminho do Windows usando fromwinpath=True
. Isso dividirá a sequência de entrada em partes, a última é a folha que você está procurando, daí a path2unix(t)[-1]
.
Se o argumento nojoin=False
, o caminho será juntado novamente, de forma que a saída seja simplesmente a sequência de entrada convertida para um formato Unix, que pode ser útil para comparar subcaminhos entre plataformas.
os.path
basta carregar ontpath
módulo internamente. Usando este módulo, é possível manipular os'\\'
separadores de caminho mesmo em máquinas Linux. Para Linux, oposixpath
módulo (resp.os.path
) Simplificará as operações do caminho para permitir apenas'/'
separadores de estilo posix .