目次
はじめに
C++で /home/user/document.txt のようなフルパスの文字列を扱う際、「ディレクトリ部分を除いた、純粋なファイル名 (document.txt) だけを抜き出したい」という場面は非常に頻繁にあります。
C++17で導入された <filesystem> ライブラリの**.filename()** メンバ関数を使えば、この処理を一行で、安全かつ直感的に行うことができます。
【前提】C++17とは?
C++17は、2017年に正式化されたC++言語の規格です。<filesystem> ライブラリはこのC++17で導入されたため、利用するにはC++17に対応したコンパイラと、適切なコンパイラ設定(および、一部の環境ではリンカ設定)が必要になります。
.filename() を使ったサンプルコード
このコードは、いくつかの異なる形式のパス文字列に対して .filename() を呼び出し、その挙動を確認します。
完成コード
#include <iostream>
#include <filesystem> // filesystemライブラリ
#include <string>
// filesystem名前空間のエイリアス
namespace fs = std::filesystem;
int main() {
// 1. 通常のフルパス
fs::path p1("/home/user/report.docx");
std::cout << p1 << " -> .filename() -> " << p1.filename() << std::endl;
// 2. ファイル名のみ
fs::path p2("archive.zip");
std::cout << p2 << " -> .filename() -> " << p2.filename() << std::endl;
// 3. 末尾がディレクトリ区切り文字のパス
fs::path p3("/home/user/");
std::cout << p3 << " -> .filename() -> " << p3.filename() << std::endl;
// 4. 末尾が "." や ".." のパス
fs::path p4("/home/user/..");
std::cout << p4 << " -> .filename() -> " << p4.filename() << std::endl;
return 0;
}
実行結果
"/home/user/report.docx" -> .filename() -> "report.docx"
"archive.zip" -> .filename() -> "archive.zip"
"/home/user/" -> .filename() -> ""
"/home/user/.." -> .filename() -> ".."
コードの解説
p1.filename()
- 機能:
pathオブジェクトが保持するパス文字列の最後の要素を、ファイル名として返します。 - 戻り値:
pathオブジェクト。std::coutなどで表示する際は、暗黙的に文字列に変換されます。 - 挙動の詳細:
"/home/user/report.docx": 最後の/以降である"report.docx"を返します。"/home/user/": 末尾がディレクトリ区切り文字の場合、ファイル名部分は存在しないと見なされ、空文字列""を返します。"/home/user/..":.や..といった特別なディレクトリ名も、ファイル名として正しく認識されます。
まとめ
今回は、C++17の <filesystem> ライブラリを使って、パスからファイル名を取得する .filename() メソッドについて解説しました。
<filesystem>ヘッダーをインクルードする。std::filesystem::pathオブジェクトを作成する。.filename()メンバ関数を呼び出すと、ディレクトリ部分が除かれた最後のパス要素が返される。
.filename() は、パス文字列を手動で解析する手間を省き、様々なOSのパス形式(/区切りや\区切り)を適切に扱ってくれる、非常に便利なツールです。
