В C++17 добавлено новое пространство имен std::filesystem. На мой взгляд он предоставляет удобный интерфейс для работы с файловой системой. Тогда как раньше приходилось складывать строки и вызывать си функции для манипуляций атрибутами файлов.
Как компилить?
- Установить С++17
- Указать линковщику флаг -lstdc++fs
1
| g++-7 main.cpp -o main -lstdc++fs
|
Начинаем эксперементировать
Для удобства я переопределил namespace. (все так делают)
1
| namespace fs = std::experimental::filesystem;
|
Первый пример
Сущность fs::path представляет путь к объектам файловой системы. И некоторые его методы.
1
2
3
4
5
6
7
| fs::path p {"./path/file.txt"};
std::cout << "parent_path: " << p.parent_path() << std::endl;
std::cout << "extension: " << p.extension() << std::endl;
std::cout << "filename: " << p.filename() << std::endl;
std::cout << "root_name: " << p.root_name() << std::endl;
std::cout << "has_relative_path: " << p.has_relative_path() << std::endl;
std::cout << "has_root_directory: " << p.has_root_directory() << std::endl;
|
На выходе получим информацию о заданном пути и файле.
1
2
3
4
5
6
| parent_path: "./path"
extension: ".txt"
filename: "file.txt"
root_name: ""
has_relative_path: 1
has_root_directory: 0
|
Кроссплатформенный разделитель
Раньше для определения разделителя в зависимости от операционной системы приходилось выкручиватся применением условных директив. Сейчас для этой цели можно применить следующий метод.
1
| std::cout << "preferred_separator: " << fs::path::preferred_separator << std::endl;
|
Output:
Применение перегруженного знака деления для получения полного пути.
Как по мне такой способ удобен тем, что при чтении, код явно говорит нам, что мы работаем с файловой системой уже в привычном нам виде.
1
2
3
4
5
6
7
| fs::path root {"/"};
fs::path httpd { "etc/httpd/" };
fs::path sites {"sites-enabled"};
fs::path conf {"site.conf"};
fs::path path_to_site_conf = root / httpd / sites / conf;
std::cout << "path_to_site_conf: " << path_to_site_conf << std::endl;
|
Output:
1
| path_to_site_conf: "/etc/httpd/sites-enabled/site.conf"
|
Рекурсивное создание и удаление каталогов
1
2
3
4
5
| fs::create_directories("banana/cocosa/mango");
fs::create_directories("banana/apple/kiwi");
system("ls -a banana/*");
fs::remove_all("banana");
system("ls -a banana/*");
|
Output:
1
2
3
4
5
6
| banana/apple:
. .. kiwi
banana/cocosa:
. .. mango
ls: cannot access 'banana/*': No such file or directory
|