Diese Bibliothek erlaubt weitgehend systemunabhängigen Zugriff auf das Dateisystem. Für eine umfassende, detailliertere Beschreibung siehe <filesystem>. Hier folgen eher Anwendungsbeispiele.
Vor der Integration in C++17 wurde zunächst Filesystem TS veröffentlicht. Notfalls kann auf diese Version zurückgegriffen werden:
#if __has_include(<filesystem>) #include <filesystem> namespace fs = std::filesystem; #elif __has_include(<experimental/filesystem>) #include <experimental/filesystem> namespace fs = std::experimental::filesystem; // g++ : link with -lstdc++fs #else #error No filesystem library. #endif
Ein Pfad fs::path
beschreibt den Weg zu einer Datei im Dateisystem absolut zur Wurzel oder relativ zu fs::current_path()
.
Er besteht aus
p.root_name()
— unter Windows ein Laufwerk C:
oder //server
,p.root_directory()
– je nach Betriebsystem /
oder \
,
Dabei sind Verzeichnisse ebenfalls Dateien, auch .
und ..
— aktuelles und übergeordnetes Verzeichnis.
Als Pfadtrenner sind sowohl /
als auch \
nutzbar.
Der Dateiname p.filename()
regulärer Dateien besteht oft aus zwei durch Punkt getrennten Teilen, p.stem()
und p.extension()
.
Wurzelverzeichnis v Dateiname E:/temp/a/simple/example.txt / ~~~~~~~~~~~~~ ------- ~~~ LW Relativpfad Stamm Erweiterung
Über die Bestandteile eines Pfades kann iteriert werden.
for (const auto& e : fs::path("E:/temp/a/simple/example.txt")) std::cout << e << ' ';
Die Ausgaben erscheinen als "quoted" strings:
"E:" "/" "temp" "a" "simple" "example.txt"
Dateien und Verzeichnisse können nur von bestimmten Nutzern gelesen, geschrieben und ausgeführt werden.
Diese Berechtigungen lassen sich in einer kurzen Zeichenkette zusammenfassen
(hier ohne set_uid
, set_gid
und sticky_bit
):
auto perm_string(fs::perms p) { auto table = { std::pair {fs::perms::owner_read, "-r"}, {fs::perms::owner_write, "-w"}, {fs::perms::owner_exec, "-x"}, {fs::perms::group_read, "-r"}, {fs::perms::group_write, "-w"}, {fs::perms::group_exec, "-x"}, {fs::perms::others_read, "-r"}, {fs::perms::others_write,"-w"}, {fs::perms::others_exec, "-x"}, }; auto sign = [p] (auto flag, const char s[]) { return s[(p & flag) != fs::perms::none]; }; std::ostringstream os; for (auto&& [flag, s] : table) os << sign(flag, s); return os.str(); }
Für einen vorgegebenen Pfad lassen sich alle Eigenschaften anzeigen:
void show(fs::path path) { if (!fs::exists(path)) { std::cout << path << " file does not exist\n"; return; } auto perms = perm_string(fs::status(path).permissions()); using clock = std::chrono::system_clock; auto time = clock::to_time_t(fs::last_write_time(path)); auto timestr = std::string(std::asctime(std::localtime(&time))); timestr.pop_back(); // get rid of '\n'; std::cout << (fs::is_directory(path)? "d" : " ") << perms << " " << timestr << " " << (fs::is_regular_file(path)? std::to_string(fs::file_size(path)) + " " : "") << path << '\n'; } void ls() { auto p = fs::current_path(); show(p); for (auto&& entry : fs::directory_iterator(p)) show(entry); }
Mit einem fs::directory_iterator
kann ein gesamtes Verzeichnis durchlaufen werden,
mit fs::recursive_directory_iterator
einschließlich Unterverzeichnisse.
Ein Demoprogramm liefert die ein wenig an das Kommando ls
erinnernde Ausgabe:
drwx------ Mon Feb 5 00:26:47 2018 "/home/jail" rw------- Mon Feb 5 00:26:45 2018 1395 "/home/jail/prog.cc" rwxr-xr-x Mon Feb 5 00:26:47 2018 2648576 "/home/jail/prog.exe"
void create() { fs::create_directories("sandbox/a/b"); std::ofstream("sandbox/file1.txt") << "Hello"; std::ofstream("sandbox/a/file2.txt") << "World"; }
void copy() { fs::create_directories("sandbox/c"); fs::rename("sandbox/a/file2.txt", "sandbox/a/file3.txt"); fs::copy("sandbox/a/file3.txt", "sandbox/c/file3.txt"); fs::copy("sandbox/a", "sandbox/copy", fs::copy_options::recursive | fs::copy_options::directories_only); // erstellt nur Verzeichnisse }
void destroy() { fs::remove("sandbox/file1.txt"); fs::remove("sandbox/a/b"); fs::remove_all("sandbox"); }
Im Fehlerfall können die Funktionen eine Ausnahme vom Typ fs::filesystem_error
werfen.
Zu allen Funktionen und Methoden exstieren Varianten,
die Fehler über eine std::error_code
-Referenz aus dem Header <system_error>
als zusätzlichen, letzten Parameter mitteilen.