回答:
os.path.split
またはos.path.basename
他の人が提案するように使用しても、すべてのケースで機能するわけではありません。Linuxでスクリプトを実行していて、クラシックなWindowsスタイルのパスを処理しようとすると、失敗します。
Windowsパスでは、パス区切り文字としてバックスラッシュまたはスラッシュを使用できます。したがって、ntpath
モジュール(Windowsで実行する場合はos.pathと同等)は、すべてのプラットフォームのすべての(1)パスで機能します。
import ntpath
ntpath.basename("a/b/c")
もちろん、ファイルがスラッシュで終わっている場合、ベース名は空になるので、それを処理する独自の関数を作成します。
def path_leaf(path):
head, tail = ntpath.split(path)
return tail or ntpath.basename(head)
検証:
>>> 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)注意点が1つあります。Linuxファイル名にはバックスラッシュが含まれている可能性があります。したがって、Linuxではr'a/b\c'
常にフォルダー内のファイルb\c
を参照し、a
Windowsでは常にフォルダーのサブフォルダーc
内のファイルを参照します。したがって、パスでスラッシュとバックスラッシュの両方が使用されている場合、関連するプラットフォームを正しく解釈できるようにする必要があります。実際には、Linuxのファイル名ではバックスラッシュがほとんど使用されないため、Windowsパスであると想定しても安全ですが、誤ってセキュリティホールを作成しないようにコーディングするときは、このことに注意してください。b
a
r'C:\path\to\file.txt'
LinuxマシンでWindowsスタイルのパス(例:)を解析する必要がある場合のみ、ntpathモジュールを使用する必要があります。それ以外の場合は、os.pathの関数を使用できます。これは、Linuxシステムでは通常、(回答で説明されているように)ファイル名にバックスラッシュ文字を使用できるためです。
os.path.basename(os.path.normpath(path))
ですか?
実際には、あなたが望むものを正確に返す関数があります
import os
print(os.path.basename(your_path))
os.path.basename(your_path)
これはうまくいきました!スクリプトパス:os.path.dirname(os.path.realpath(__file__))
とスクリプト名:が必要os.path.basename(os.path.realpath(__file__))
でした。ありがとう!
'C:\\temp\\bla.txt'
代わりに取得することです。
os.path.split はあなたが探している関数です
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')
尾はあなたが望むもの、ファイル名です。
詳細については、Python OSモジュールのドキュメントをご覧ください
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
あなたの例では、返すために右側からスラッシュを取り除く必要もありますc
:
>>> import os
>>> path = 'a/b/c/'
>>> path = path.rstrip(os.sep) # strip the slash from the right side
>>> os.path.basename(path)
'c'
セカンドレベル:
>>> os.path.filename(os.path.dirname(path))
'b'
更新:私lazyr
は正しい答えを提供したと思います。私のコードは、UNIXシステムのWindowsのようなパスでは機能せず、逆に、WindowsシステムのUNIXのようなパスでも機能しません。
r"a\b\c"
Linuxでも"a/b/c"
Windows でも機能しません。
os.path.basename(path)
場合にのみ動作しますos.path.isfile(path)
ですTrue
。したがって、これpath = 'a/b/c/'
は有効なファイル名ではありません...
os.path.basename("a/b/c/")
戻ります""
。
lazyr
あなたが正しいです!私はそれについて考えていませんでした。ただやっても大丈夫path = path.replace('\\', '/')
ですか?
fname = str("C:\Windows\paint.exe").split('\\')[-1:][0]
これが返されます:paint.exe
パスまたはOSに関する分割関数のsep値を変更します。
fname = str(path).split('/')[-1]
ファイルパスが「/」で終わっておらず、ディレクトリが「/」で区切られていない場合は、次のコードを使用します。一般的に知っているように、パスは「/」で終わっていません。
import os
path_str = "/var/www/index.html"
print(os.path.basename(path_str))
ただし、URLが「/」で終わるような場合には、次のコードを使用します。
import os
path_str = "/home/some_str/last_str/"
split_path = path_str.rsplit("/",1)
print(os.path.basename(split_path[0]))
しかし、パスが通常「\」で分割されている場合、Windowsのパスで一般的に見られるように、次のコードを使用できます。
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]))
OSタイプをチェックして結果を返すことで、両方を1つの関数に結合できます。
これはLinuxとWindowsでも標準ライブラリで動作します
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]
結果:
['c', 'c', 'c', 'c', 'c', 'c', 'c']
これは正規表現のみのソリューションで、どのOSのどのOSパスでも機能するようです。
他のモジュールは必要なく、前処理も必要ありません。
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']
更新:
可能性のあるファイル名だけが必要な場合、存在する場合(つまり、/a/b/
はdirでありc:\windows\
)は、正規表現をに変更しますr'[^\\/]+(?![\\/])$'
。「正規表現のチャレンジ」の場合、これはスラッシュの正の前方先読みを負の前方先読みに変更し、スラッシュで終わるパス名がパス名の最後のサブディレクトリの代わりに何も返さないようにします。もちろん、潜在的なファイル名が実際にファイルを参照していること、そのために使用する必要があるos.path.is_dir()
かos.path.is_file()
どうかの保証はありません。
これは次のように一致します。
/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
たぶん私のオールインワンソリューションで重要ないくつかの新しいものがないかもしれません(一時ファイルを作成するための一時ファイルについて:D)
import tempfile
abc = tempfile.NamedTemporaryFile(dir='/tmp/')
abc.name
abc.name.replace("/", " ").split()[-1]
の値を取得abc.name
すると、次のような文字列になります。'/tmp/tmpks5oksk7'
つまり/
、をスペースに置き換えてを.replace("/", " ")
呼び出すことができますsplit()
。それはリストを返し、リストの最後の要素を取得します[-1]
モジュールをインポートする必要はありません。
ダブルバックスラッシュパスは見たことがありませんが、存在しますか?os
それらのpythonモジュールの組み込み機能は失敗します。他のすべては機能します、またあなたによって与えられた警告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セパレータは、Unixファイル名またはWindowsパスに含めることができます。Unixセパレータは、Unixパスにのみ存在できます。Unixセパレータの存在は、Windows以外のパスを示します。
以下は、OS固有のセパレーターで(末尾のセパレーターをカットして)除去し、次に分割して右端の値を返します。醜いですが、上記の仮定に基づいて簡単です。仮定が正しくない場合は、更新してください。この応答を更新して、より正確な条件に一致させます。
a.rstrip("\\\\" if a.count("/") == 0 else '/').split("\\\\" if a.count("/") == 0 else '/')[-1]
サンプルコード:
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
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']
これはWindowsとLinuxの両方で機能します。
Python 2と3の両方で、モジュール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)
使用法:
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']
あなたのテストケースで:
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
ここでの考え方はpathlib2
、プラットフォームに応じて異なるデコーダーを使用して、すべてのパスをの統一された内部表現に変換することです。幸いなことに、どのパスでも機能pathlib2
するという一般的なデコーダーが含まPurePath
れています。これが機能しない場合は、を使用してWindowsパスの認識を強制できますfromwinpath=True
。これにより、入力文字列が分割されます。最後の文字列は、探している葉、つまりpath2unix(t)[-1]
です。
引数のnojoin=False
場合、パスは結合され、出力は単にUnix形式に変換された入力文字列になるため、プラットフォーム間でサブパスを比較するのに役立ちます。
os.path
ロードするだけntpath
です。このモジュールを使用すると'\\'
、Linuxマシンでもパス区切り文字を処理できます。Linuxの場合、posixpath
モジュール(またはos.path
)はパス操作を単純化して、posixスタイルの'/'
セパレータのみを許可します。