目次
はじめに
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のパス形式(/
区切りや\
区切り)を適切に扱ってくれる、非常に便利なツールです。