C++17 filesystem 库 学习笔记-CSDN博客 (2024)

C++17 filesystem 库 学习笔记

  • Filesystem library
    • 1、类
    • 2、非成员函数
      • 2.1、std::filesystem::absolute
      • 2.2、std::filesystem::canonical, std::filesystem::weakly_canonical
      • 2.3、std::filesystem::relative, std::filesystem::proximate
      • 2.4、std::filesystem::copy
      • 2.5、std::filesystem::copy_file
      • 2.6、std::filesystem::copy_symlink
      • 2.7、std::filesystem::create_directory, std::filesystem::create_directories
      • 2.8、std::filesystem::create_hard_link
      • 2.9、std::filesystem::create_symlink, std::filesystem::create_directory_symlink
      • 2.10、std::filesystem::current_path
      • 2.11、std::filesystem::exists
      • 2.12、std::filesystem::equivalent
      • 2.13、std::filesystem::file_size
      • 2.14、std::filesystem::hard_link_count
      • 2.15、std::filesystem::last_write_time
      • 2.16、std::filesystem::permissions
      • 2.17、std::filesystem::read_symlink
      • 2.18、std::filesystem::remove, std::filesystem::remove_all
      • 2.19、std::filesystem::rename
      • 2.20、std::filesystem::resize_file
      • 2.21、std::filesystem::space
      • 2.22、std::filesystem::status, std::filesystem::symlink_status
      • 2.23、std::filesystem::temp_directory_path
    • 3、文件类型
      • 3.1、std::filesystem::is_block_file
      • 3.2、std::filesystem::is_character_file
      • 3.3、std::filesystem::is_directory
      • 3.4、std::filesystem::is_empty
      • 3.5、std::filesystem::is_fifo
      • 3.6、std::filesystem::is_other
      • 3.7、std::filesystem::is_regular_file
      • 3.8、std::filesystem::is_socket
      • 3.9、std::filesystem::is_symlink
      • 3.10、std::filesystem::status_known

Filesystem library

官方文档:https://en.cppreference.com/w/cpp/filesystem

Filesystem 由 boost.filesystem 发展而来,自 C++17 开始引入到 ISO C++ 中,用于操作文件系统及其组件(路径、常规文件及文件夹等)。如果希望在较低版本的 C++ 编译器中使用 filesystem,需要换用 boost。

1、类

  • 定义于头文件 <filiesystem>
  • 定义于命名空间 std::filesystem

这里面的各类不再一一列举,它们的功能直接通过下面表格里的链接跳转到官方页面即可。

path路径
filesystem_error文件系统错误异常
directory_entry文件夹
directory_iterator文件夹内容的迭代器
recursive_directory_iterator递归式迭代指定路径下的所有文件及文件夹
file_status文件类型及权限
space_info文件系统中可用的剩余空间信息
file_type文件类型
perms文件系统权限标识符
perm_options指明权限操作的语义
copy_options指明复制操作的语义
directory_options对文件夹内容进行迭代时的选项
file_time_type文件时间信息

2、非成员函数

  • 定义于头文件 <filiesystem>
  • 定义于命名空间 std::filesystem
absolute绝对路径
canonical、weakly_canonical将相对路径转为绝对路径
relative、proximate相对路径
copy复制文件或者文件夹
copy_file复制文件内容
copy_symlink复制符号链接
create_directory、create_directories创建新文件夹
create_hard_link创建硬链接
create_symlink、create_directory_symlink创建符号链接
current_path返回或修改当前工作路径
exists判断路径是否存在
equivalent判断两个路径是否相同
file_size返回文件大小
hard_link_count返回指定文件的硬链接数量
last_write_time获取或设置最近一次修改数据的时间
permissions修改访问权限
read_symlink获取符号链接的目标
remove、remove_all删除文件或空文件夹,后者可递归式删除非空文件夹
rename重命名文件或文件夹
resize_file改变常规文件的大小
space确定文件系统中的可用剩余空间
status、symlink_status确定文件属性;检查符号链接目标
temp_directory_path返回一个存放临时文件的文件夹

2.1、std::filesystem::absolute

定义于 <filesystem>

返回包含 p 在内的绝对路径

path absolute( const std::filesystem::path& p );path absolute( const std::filesystem::path& p, std::error_code& ec );

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

第一个函数在底层系统 API 错误上抛出 std::filesystem::filesystem_error,构建时将 p 作为第一个路径参数,将系统错误代码作为错误代码参数。

如果系统 API 调用失败,第二个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()。

注意:
对 p 不存在的情况,并非异常;

对基于 POSIX 的系统来说,std::filesystem::absolute(p) 等价于 std::filesystem::current_path() / p

对 Windows 来说,std::filesystem::absolute 可能是基于 GetFullPathNameW 开发的。

案例:

#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ std::filesystem::path p = "foo.c"; std::cout << "Current path is " << std::filesystem::current_path() << '\n'; std::cout << "Absolute path for " << p << " is " << fs::absolute(p) << '\n';}

输出:

Current path is "/tmp/1666297965.0051296"Absolute path for "foo.c" is "/tmp/1666297965.0051296/foo.c"

2.2、std::filesystem::canonical, std::filesystem::weakly_canonical

定义于 <filesystem>

将 p 转换为规范的绝对路径,这两个函数的差异可以详见后面的案例

path canonical( const std::filesystem::path& p );path canonical( const std::filesystem::path& p, std::error_code& ec );path weakly_canonical( const std::filesystem::path& p );path weakly_canonical( const std::filesystem::path& p, std::error_code& ec );

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

不带 ec 的几个函数在底层系统 API 错误上抛出 std::filesystem::filesystem_error,构建时将 p 作为第一个路径参数,将系统错误代码作为错误代码参数。

如果系统 API 调用失败,另外几个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()。

案例:

#include <filesystem>#include <iostream> int main(){ /* set up sandbox directories: a └── b ├── c1 │ └── d <== current path └── c2 └── e */ auto old = std::filesystem::current_path(); auto tmp = std::filesystem::temp_directory_path(); std::filesystem::current_path(tmp); auto d1 = tmp / "a/b/c1/d"; auto d2 = tmp / "a/b/c2/e"; std::filesystem::create_directories(d1); std::filesystem::create_directories(d2); std::filesystem::current_path(d1); auto p1 = std::filesystem::path("../../c2/./e"); auto p2 = std::filesystem::path("../no-such-file"); std::cout << "Current path is " << std::filesystem::current_path() << '\n' << "Canonical path for " << p1 << " is " << std::filesystem::canonical(p1) << '\n' << "Weakly canonical path for " << p2 << " is " << std::filesystem::weakly_canonical(p2) << '\n'; try { [[maybe_unused]] auto x_x = std::filesystem::canonical(p2); // NOT REACHED } catch (const std::exception& ex) { std::cout << "Canonical path for " << p2 << " threw exception:\n" << ex.what() << '\n'; } // cleanup std::filesystem::current_path(old); const auto count = std::filesystem::remove_all(tmp / "a"); std::cout << "Deleted " << count << " files or directories.\n";}

输出:

Current path is "/tmp/a/b/c1/d"Canonical path for "../../c2/./e" is "/tmp/a/b/c2/e"Weakly canonical path for "../no-such-file" is "/tmp/a/b/c1/no-such-file"Canonical path for "../no-such-file" threw exception:filesystem error: in canonical: No such file or directory [../no-such-file] [/tmp/a/b/c1/d]Deleted 6 files or directories.

2.3、std::filesystem::relative, std::filesystem::proximate

定义于 <filesystem>

返回相对路径,具体使用方法见后面的案例

path relative( const std::filesystem::path& p, std::error_code& ec );path relative( const std::filesystem::path& p, const std::filesystem::path& base = std::filesystem::current_path() );path relative( const std::filesystem::path& p, const std::filesystem::path& base, std::error_code& ec );path proximate( const std::filesystem::path& p, std::error_code& ec );path proximate( const std::filesystem::path& p, const std::filesystem::path& base = std::filesystem::current_path() );path proximate( const std::filesystem::path& p, const std::filesystem::path& base, std::error_code& ec );

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

不带 ec 参数的函数在底层系统 API 错误上抛出 std::filesystem::filesystem_error,构建时将 p 作为第一个路径参数,将系统错误代码作为错误代码参数。

如果系统 API 调用失败,另外几个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()。

案例:

#include <filesystem>#include <iostream> void show(std::filesystem::path x, std::filesystem::path y){ std::cout << "x:\t\t " << x << "\ny:\t\t " << y << '\n' << "relative(x, y): " << std::filesystem::relative(x, y) << '\n' << "proximate(x, y): " << std::filesystem::proximate(x, y) << "\n\n";} int main(){ show("/a/b/c", "/a/b"); show("/a/c", "/a/b"); show("c", "/a/b"); show("/a/b", "c");}

输出:

x: "/a/b/c"y: "/a/b"relative(x, y): "c"proximate(x, y): "c" x: "/a/c"y: "/a/b"relative(x, y): "../c"proximate(x, y): "../c" x: "c"y: "/a/b"relative(x, y): ""proximate(x, y): "c" x: "/a/b"y: "c"relative(x, y): ""proximate(x, y): "/a/b"

2.4、std::filesystem::copy

定义于 <filesystem>

可以以指定复制方案的方式,对文件或者文件夹进行复制

void copy( const std::filesystem::path& from, const std::filesystem::path& to );void copy( const std::filesystem::path& from, const std::filesystem::path& to, std::error_code& ec );void copy( const std::filesystem::path& from, const std::filesystem::path& to, std::filesystem::copy_options options );void copy( const std::filesystem::path& from, const std::filesystem::path& to, std::filesystem::copy_options options, std::error_code& ec );

案例:

#include <cstdlib>#include <filesystem>#include <fstream>#include <iostream>namespace fs = std::filesystem; int main(){ fs::create_directories("sandbox/dir/subdir"); std::ofstream("sandbox/file1.txt").put('a'); fs::copy("sandbox/file1.txt", "sandbox/file2.txt"); // copy file fs::copy("sandbox/dir", "sandbox/dir2"); // copy directory (non-recursive) const auto copyOptions = fs::copy_options::update_existing | fs::copy_options::recursive | fs::copy_options::directories_only ; fs::copy("sandbox", "sandbox_copy", copyOptions); static_cast<void>(std::system("tree")); fs::remove_all("sandbox"); fs::remove_all("sandbox_copy");}

输出:

.├── sandbox│ ├── dir│ │ └── subdir│ ├── dir2│ ├── file1.txt│ └── file2.txt└── sandbox_copy ├── dir │ └── subdir └── dir2 8 directories, 2 files

异常的情况与其他函数基本相同,后面不再赘述。

函数在执行时的具体行为

  • 首先,在执行任何其他操作之前,只需对下面的两个函数进行一次调用,即可获得 from 的类型和权限:
    • std::filesystem::symlink_status(如果在 options 中指定了 copy_options::skip_symlinks, copy_options::copy_symlinks, 或 copy_options::create_symlinks
    • std::filesystem::status (其他情况)
  • 如果有必要,只需对下面的两个函数进行一次调用,即可获得 to 的状态:
    • std::filesystem::symlink_status(如果在 options 中指定了 copy_options::skip_symlinks, 或 copy_options::create_symlinks))
    • std::filesystem::status (包含在 options 中指定 copy_options::copy_symlinks 在内的其他情况)
  • 如果 from 或 to 中有 implementation-defined 文件类型,则函数的执行效果也是 implementation-defined;
  • 如果 from 不存在,函数将报错;
  • 如果 from 与 to 是相同的,函数将报错(具体来说,两者是通过函数 std::filesystem::equivalent 判定是否相同的);
  • 如果 from 或 to 不是常规文件、文件夹或者符号链接,则函数报错(通过函数 std::filesystem::is_other 判定的);
  • 如果 from 是文件夹,to 是常规文件,则函数报错;
  • 如果 from 是符号链接,则有(以下三条,优先级逐渐降低):
    • 如果 options 中有 copy_options::skip_symlink,则函数啥也不干
    • 否则,如果 to 不存在,且 options 中有 copy_options::copy_symlinks,则函数的行为与 copy_symlink(from, to) 一致;
    • 对不含上面情况的其他情形,函数报错;
  • 如果 from 是常规文件,则有(以下五条,优先级逐渐降低):
    • 如果设置 options 为 copy_options::directories_only,则函数啥也不干;
    • 否则,如果 options 中有 copy_options::create_symlinks,函数创建一个符号链接(from 必须为绝对路径)
    • 否则,如果 options 中有 copy_options::create_hard_links,函数创建一个硬链接
    • 否则,如果 to 是文件夹,那函数的行为与 copy_file(from, to/from.filename(), options) 相同(即在 to 中创建一个文件)
    • 否则,与函数 copy_file(from, to, options) 的表现相同。
  • 如果 from 是文件夹,并且在 options 中设置了 copy_options::create_symlinks,函数将会报错,相应的错误代码为 std::make_error_code(std::errc::is_a_directory)
  • 如果 from 是文件夹,而 options 中设置了 copy_options::recursivecopy_options::none,则:
    • 如果 to 不存在,函数将先执行 create_directory(to, from)
    • 然后,在 from 中含有的文件中进行迭代(使用了 for (const std::filesystem::directory_entry& x : std::filesystem::directory_iterator(from))),并在每个子文件夹中递归地调用 copy(x.path(), to/x.path().filename(), options | in-recursive-copy)
  • 对 from 与 to 的其他情况,函数什么也不做。

2.5、std::filesystem::copy_file

定义于 <filesystem>

可以以指定复制方案的方式,对文件进行复制

bool copy_file( const std::filesystem::path& from, const std::filesystem::path& to );bool copy_file( const std::filesystem::path& from, const std::filesystem::path& to, std::error_code& ec );bool copy_file( const std::filesystem::path& from, const std::filesystem::path& to, std::filesystem::copy_options options );bool copy_file( const std::filesystem::path& from, const std::filesystem::path& to, std::filesystem::copy_options options, std::error_code& ec );

案例:

#include <filesystem>#include <fstream>#include <iostream>namespace fs = std::filesystem; int main(){ fs::create_directory("sandbox"); std::ofstream("sandbox/file1.txt").put('a'); fs::copy_file("sandbox/file1.txt", "sandbox/file2.txt"); // now there are two files in sandbox: std::cout << "file1.txt holds: " << std::ifstream("sandbox/file1.txt").rdbuf() << '\n'; std::cout << "file2.txt holds: " << std::ifstream("sandbox/file2.txt").rdbuf() << '\n'; // fail to copy directory fs::create_directory("sandbox/abc"); try { fs::copy_file("sandbox/abc", "sandbox/def"); } catch (fs::filesystem_error& e) { std::cout << "Could not copy sandbox/abc: " << e.what() << '\n'; } fs::remove_all("sandbox");}

输出:

file1.txt holds: afile2.txt holds: aCould not copy sandbox/abc: copy_file: Is a directory: "sandbox/abc", "sandbox/def"

函数执行时的行为

  • 前两个函数相当于在后两个函数中为 options 设置 copy_options::none
  • 后两个函数中,基于 options 中的设置内容,从 from 中复制一份文件到 to 中。如果 options 中的任何copy_options 选项组中存在多个 option,则函数的行为未定义。
    • 如果 !filesystem::is_regular_file(from) 为 true,则函数报错;
    • 否则,如果 to 不存在,
      • 复制 from 的内容及属性;
    • 否则,如果 to 已经存在了,
      • 如果有下面的情况,函数就报错:
        • to 与 from 相同(由 filesystem::equivalent(from, to) 判定)
        • to 不是常规文件(由 ! filesystem::is_regular_file(to) 判定)
        • options 中没有设置控制选项
      • 否则,如果在 options 中设置了 copy_options::skip_existing,则函数什么也不做;
      • 否则,如果在 options 中设置了 copy_options::overwrite_existing,执行复制操作,替换掉已有文件;
      • 否则,如果在 options 中设置了 copy_options::update_existing,则仅在 from 比 to 较新的时候才会进行复制(用 filesystem::last_write_time() 的执行结果判定 from 是否比 to 新)

2.6、std::filesystem::copy_symlink

定义于 <filesystem>

可以以指定复制方案的方式,对符号链接进行复制

第一个函数依据 from 是文件还是文件夹,将以 f(read_symlink(from), to) 的形式调用函数 create_symlinkcreate_directory_symlink

第二个函数依据 from 是文件还是文件夹,将以 f(read_symlink(from), to, ec) 的形式调用函数 create_symlinkcreate_directory_symlink

void copy_symlink( const std::filesystem::path& from, const std::filesystem::path& to);void copy_symlink( const std::filesystem::path& from, const std::filesystem::path& to, std::error_code& ec ) noexcept;

2.7、std::filesystem::create_directory, std::filesystem::create_directories

bool create_directory( const std::filesystem::path& p );bool create_directory( const std::filesystem::path& p, std::error_code& ec ) noexcept;bool create_directory( const std::filesystem::path& p, const std::filesystem::path& existing_p );bool create_directory( const std::filesystem::path& p, const std::filesystem::path& existing_p, std::error_code& ec ) noexcept;bool create_directories( const std::filesystem::path& p );bool create_directories( const std::filesystem::path& p, std::error_code& ec );

第三和第四个函数不同于另外四个,它俩创建的新文件夹的属性是从 existing_p 中复制来的(仅在 POSIX 系统中是这样的,在 Windows 中并未复制属性值):

stat(existing_p.c_str(), &attributes_stat)mkdir(p.c_str(), attributes_stat.st_mode)

案例:

#include <cassert>#include <cstdlib>#include <filesystem> int main(){ std::filesystem::current_path(std::filesystem::temp_directory_path()); // Basic usage std::filesystem::create_directories("sandbox/1/2/a"); std::filesystem::create_directory("sandbox/1/2/b"); // Directory already exists (false returned, no error) assert(!std::filesystem::create_directory("sandbox/1/2/b")); // Permissions copying usage std::filesystem::permissions( "sandbox/1/2/b", std::filesystem::perms::others_all, std::filesystem::perm_options::remove ); std::filesystem::create_directory("sandbox/1/2/c", "sandbox/1/2/b"); std::system("ls -l sandbox/1/2"); std::system("tree sandbox"); std::filesystem::remove_all("sandbox");}

输出:

drwxr-xr-x 2 user group 4096 Apr 15 09:33 adrwxr-x--- 2 user group 4096 Apr 15 09:33 bdrwxr-x--- 2 user group 4096 Apr 15 09:33 csandbox└── 1 └── 2 ├── a ├── b └── c

2.8、std::filesystem::create_hard_link

void create_hard_link( const std::filesystem::path& target, const std::filesystem::path& link );void create_hard_link( const std::filesystem::path& target, const std::filesystem::path& link, std::error_code& ec ) noexcept;

该函数将为 target 创建一个硬链接,其中 target 必须设定;
一旦被创建,link 与 target 就成为指向同一个文件的两个逻辑名(它们是等价的),如果 target 被删除,原文件将继续存在,link 也继续指向它。

注意:
一些操作系统不支持硬链接,或者仅在常规文件中支持;

有些操作系统可能支持硬链接,但其中的文件系统可能不支持,例如闪存中的 FAT 文件系统;

一些文件系统对每个文件所能拥有的硬链接的数量进行了限制;

仅管理员具有硬链接到文件夹的权限;

硬链接通常不能跨越文件系统边界。

特殊的路径名 . 是向其父文件夹的一个硬链接,而 .. 是向其父文件夹的父文件夹的一个硬链接。

案例:

#include <filesystem>#include <fstream>#include <iostream>namespace fs = std::filesystem; int main(){ fs::create_directories("sandbox/subdir"); std::ofstream("sandbox/a").put('a'); // create regular file fs::create_hard_link("sandbox/a", "sandbox/b"); fs::remove("sandbox/a"); // read from the original file via surviving hard link char c = std::ifstream("sandbox/b").get(); std::cout << c << '\n'; fs::remove_all("sandbox");}

输出:

a

2.9、std::filesystem::create_symlink, std::filesystem::create_directory_symlink

void create_symlink( const std::filesystem::path& target, const std::filesystem::path& link );void create_symlink( const std::filesystem::path& target, const std::filesystem::path& link, std::error_code& ec ) noexcept;void create_directory_symlink( const std::filesystem::path& target, const std::filesystem::path& link );void create_directory_symlink( const std::filesystem::path& target, const std::filesystem::path& link, std::error_code& ec ) noexcept;

创建符号链接

注意:
一些操作系统并不支持符号链接,或者仅在常规文件上支持;

有些操作系统可能支持符号链接,但其中的文件系统可能不支持,例如闪存中的 FAT 文件系统;

与硬链接一样,符号链接允许文件同时拥有多个逻辑名,但硬链接要求原文件必须存在,而符号链接可以独立于原文件存在,且能跨越文件系统边界。

案例:

#include <cassert>#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ fs::create_directories("sandbox/subdir"); fs::create_symlink("target", "sandbox/sym1"); fs::create_directory_symlink("subdir", "sandbox/sym2"); for (auto it = fs::directory_iterator("sandbox"); it != fs::directory_iterator(); ++it) if (is_symlink(it->symlink_status())) std::cout << *it << "->" << read_symlink(*it) << '\n'; assert(std::filesystem::equivalent("sandbox/sym2", "sandbox/subdir")); fs::remove_all("sandbox");}

输出:

"sandbox/sym1"->"target""sandbox/sym2"->"subdir"

2.10、std::filesystem::current_path

path current_path();path current_path( std::error_code& ec );void current_path( const std::filesystem::path& p );void current_path( const std::filesystem::path& p, std::error_code& ec ) noexcept;

返回或者修改当前的工作路径

案例:

#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ std::cout << "Current path is " << fs::current_path() << '\n'; // (1) fs::current_path(fs::temp_directory_path()); // (3) std::cout << "Current path is " << fs::current_path() << '\n';}

输出:

Current path is "D:/local/ConsoleApplication1"Current path is "E:/Temp"

2.11、std::filesystem::exists

bool exists( std::filesystem::file_status s ) noexcept;bool exists( const std::filesystem::path& p );bool exists( const std::filesystem::path& p, std::error_code& ec ) noexcept;

检查当前的文件或文件夹是否存在;

第一个函数等价于 status_known(s) && s.type() != file_type::not_found

第二第三个函数中,令 s 为用 status(p)status(p, ec) 决定的 std::filesystem::file_status,则这两个函数返回的值为 exists(s),第三个函数在 status_known(s) 为真时,将调用 ec.clear()

案例:

#include <cstdint>#include <filesystem>#include <fstream>#include <iostream>namespace fs = std::filesystem; void demo_exists(const fs::path& p, fs::file_status s = fs::file_status{}){ std::cout << p; if (fs::status_known(s) ? fs::exists(s) : fs::exists(p)) std::cout << " exists\n"; else std::cout << " does not exist\n";} int main(){ const fs::path sandbox{"sandbox"}; fs::create_directory(sandbox); std::ofstream{sandbox/"file"}; // create regular file fs::create_symlink("non-existing", sandbox/"symlink"); demo_exists(sandbox); for (const auto& entry : fs::directory_iterator(sandbox)) demo_exists(entry, entry.status()); // use cached status from directory entry fs::remove_all(sandbox);}

输出:

"sandbox" exists"sandbox/symlink" does not exist"sandbox/file" exists

2.12、std::filesystem::equivalent

bool equivalent( const std::filesystem::path& p1, const std::filesystem::path& p2 );bool equivalent( const std::filesystem::path& p1, const std::filesystem::path& p2, std::error_code& ec ) noexcept;

用于检查两个路径是否指向同一个文件系统实体
如果 p1 或者 p2 不存在,函数将报错。

注意:
判定相等的方式:两个路径指向的实体在同一个设备的同一个位置。对 POSIX 来说,在通过 stat() 获得的两个路径的 stat 结构体中,st_devst_ino 是对应相等的。

另外,同一个文件或文件夹的所有硬链接是等价的,同一个文件系统中的符号链接与其 target 之间是等价的。

案例:

#include <cstdint>#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ // hard link equivalency fs::path p1 = "."; fs::path p2 = fs::current_path(); if (fs::equivalent(p1, p2)) std::cout << p1 << " is equivalent to " << p2 << '\n'; // symlink equivalency for (const fs::path lib : {"/lib/libc.so.6", "/lib/x86_64-linux-gnu/libc.so.6"}) { try { p2 = lib.parent_path() / fs::read_symlink(lib); } catch (std::filesystem::filesystem_error const& ex) { std::cout << ex.what() << '\n'; continue; } if (fs::equivalent(lib, p2)) std::cout << lib << " is equivalent to " << p2 << '\n'; }}

输出:

"." is equivalent to "/var/tmp/test"filesystem error: read_symlink: No such file or directory [/lib/libc.so.6]"/lib/x86_64-linux-gnu/libc.so.6" is equivalent to "/lib/x86_64-linux-gnu/libc-2.23.so"

2.13、std::filesystem::file_size

std::uintmax_t file_size( const std::filesystem::path& p );std::uintmax_t file_size( const std::filesystem::path& p, std::error_code& ec ) noexcept;

当 p 不存在时,函数报错;

案例:

#include <cmath>#include <filesystem>#include <fstream>#include <iostream>namespace fs = std::filesystem; struct HumanReadable{ std::uintmax_t size{}; private: friend std::ostream& operator<<(std::ostream& os, HumanReadable hr) { int o{}; double mantissa = hr.size; for (; mantissa >= 1024.; mantissa /= 1024., ++o); os << std::ceil(mantissa * 10.) / 10. << "BKMGTPE"[o]; return o ? os << "B (" << hr.size << ')' : os; }}; int main(int, char const* argv[]){ fs::path example = "example.bin"; fs::path p = fs::current_path() / example; std::ofstream(p).put('a'); // create file of size 1 std::cout << example << " size = " << fs::file_size(p) << '\n'; fs::remove(p); p = argv[0]; std::cout << p << " size = " << HumanReadable{fs::file_size(p)} << '\n'; try { std::cout << "Attempt to get size of a directory:\n"; [[maybe_unused]] auto x_x = fs::file_size("/dev"); } catch (fs::filesystem_error& e) { std::cout << e.what() << '\n'; } for (std::error_code ec; fs::path bin : {"cat", "mouse"}) { bin = "/bin"/bin; if (const std::uintmax_t size = fs::file_size(bin, ec); ec) std::cout << bin << " : " << ec.message() << '\n'; else std::cout << bin << " size = " << HumanReadable{size} << '\n'; }}

输出:

"example.bin" size = 1"./a.out" size = 22KB (22512)Attempt to get size of a directory:filesystem error: cannot get file size: Is a directory [/dev]"/bin/cat" size = 50.9KB (52080)"/bin/mouse" : No such file or directory

2.14、std::filesystem::hard_link_count

std::uintmax_t hard_link_count( const std::filesystem::path& p );std::uintmax_t hard_link_count( const std::filesystem::path& p, std::error_code& ec ) noexcept;

返回 p 的硬链接数量

案例:

#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ // On a POSIX-style filesystem, each directory has at least 2 hard links: // itself and the special member pathname "." fs::path p = fs::current_path(); std::cout << "Number of hard links for current path is " << fs::hard_link_count(p) << '\n'; // Each ".." is a hard link to the parent directory, so the total number // of hard links for any directory is 2 plus number of direct subdirectories p = fs::current_path() / ".."; // Each dot-dot is a hard link to parent std::cout << "Number of hard links for .. is " << fs::hard_link_count(p) << '\n';}

输出:

Number of hard links for current path is 2Number of hard links for .. is 3

2.15、std::filesystem::last_write_time

std::filesystem::file_time_type last_write_time( const std::filesystem::path& p );std::filesystem::file_time_type last_write_time( const std::filesystem::path& p, std::error_code& ec ) noexcept;void last_write_time( const std::filesystem::path& p, std::filesystem::file_time_type new_time );void last_write_time( const std::filesystem::path& p, std::filesystem::file_time_type new_time, std::error_code& ec ) noexcept;

返回最近一次修改的时间

案例:

#include <chrono>#include <filesystem>#include <format>#include <fstream>#include <iostream> using namespace std::chrono_literals; int main(){ auto p = std::filesystem::temp_directory_path() / "example.bin"; std::ofstream{p.c_str()}.put('a'); // create file std::filesystem::file_time_type ftime = std::filesystem::last_write_time(p); std::cout << std::format("File write time is {}\n", ftime); // move file write time 1 hour to the future std::filesystem::last_write_time(p, ftime + 1h); // read back from the filesystem ftime = std::filesystem::last_write_time(p); std::cout << std::format("File write time is {}\n", ftime); std::filesystem::remove(p);}

输出:

File write time is 2023-09-04 19:33:24.702639224File write time is 2023-09-04 20:33:24.702639224

2.16、std::filesystem::permissions

void permissions( const std::filesystem::path& p, std::filesystem::perms prms, std::filesystem::perm_options opts = perm_options::replace );void permissions( const std::filesystem::path& p, std::filesystem::perms prms, std::error_code& ec ) noexcept;void permissions( const std::filesystem::path& p, std::filesystem::perms prms, std::filesystem::perm_options opts, std::error_code& ec );

修改文件权限
在设置 prms 与 opts 参数时,有以下效果:

  • 如果 opts 为 perm_options::replace,文件权限将被设为 prms & std::filesystem::perms::mask
  • 如果 opts 为 perm_options::add,文件权限将被设为 status(p).permissions() | (prms & perms::mask)
  • 如果 opts 为 perm_options::remove,文件权限将被设为 status(p).permissions() & ~(prms & perms::mask)

opts 仅能被设为 replace、add 与 remove 中的一个。

案例:

#include <filesystem>#include <fstream>#include <iostream> void demo_perms(std::filesystem::perms p){ using std::filesystem::perms; auto show = [=](char op, perms perm) { std::cout << (perms::none == (perm & p) ? '-' : op); }; show('r', perms::owner_read); show('w', perms::owner_write); show('x', perms::owner_exec); show('r', perms::group_read); show('w', perms::group_write); show('x', perms::group_exec); show('r', perms::others_read); show('w', perms::others_write); show('x', perms::others_exec); std::cout << '\n';} int main(){ std::ofstream("test.txt"); // create file std::cout << "Created file with permissions: "; demo_perms(std::filesystem::status("test.txt").permissions()); std::filesystem::permissions( "test.txt", std::filesystem::perms::owner_all | std::filesystem::perms::group_all, std::filesystem::perm_options::add ); std::cout << "After adding u+rwx and g+rwx: "; demo_perms(std::filesystem::status("test.txt").permissions()); std::filesystem::remove("test.txt");}

输出:

Created file with permissions: rw-r--r--After adding u+rwx and g+wrx: rwxrwxr--

2.17、std::filesystem::read_symlink

std::filesystem::path read_symlink( const std::filesystem::path& p );std::filesystem::path read_symlink( const std::filesystem::path& p, std::error_code& ec );

返回符号链接指向的目标路径

案例:

#include <filesystem>#include <iostream> namespace fs = std::filesystem; int main(){ for (fs::path p : {"/usr/bin/gcc", "/bin/cat", "/bin/mouse"}) { std::cout << p; fs::exists(p) ? fs::is_symlink(p) ? std::cout << " -> " << fs::read_symlink(p) << '\n' : std::cout << " exists but it is not a symlink\n" : std::cout << " does not exist\n"; }}

输出:

"/usr/bin/gcc" -> "gcc-5""/bin/cat" exists but it is not a symlink"/bin/mouse" does not exist

2.18、std::filesystem::remove, std::filesystem::remove_all

bool remove( const std::filesystem::path& p );bool remove( const std::filesystem::path& p, std::error_code& ec ) noexcept;std::uintmax_t remove_all( const std::filesystem::path& p );std::uintmax_t remove_all( const std::filesystem::path& p, std::error_code& ec );

删除文件或者文件夹

第一个函数在处理文件夹时,仅能处理空的;如果想删除文件夹及其所有内容,应该使用第二个函数

注意:
在 POSIX 系统中,相当于在执行 unlinkrmdir

在 Windows 中,在执行 DeleteFileWRemoveDirectoryW

案例:

#include <cstdint>#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ fs::path tmp{std::filesystem::temp_directory_path()}; std::filesystem::create_directories(tmp / "abcdef/example"); std::uintmax_t n{fs::remove_all(tmp / "abcdef")}; std::cout << "Deleted " << n << " files or directories\n";}

输出:

Deleted 2 files or directories

2.19、std::filesystem::rename

void rename( const std::filesystem::path& old_p, const std::filesystem::path& new_p );void rename( const std::filesystem::path& old_p, const std::filesystem::path& new_p, std::error_code& ec ) noexcept;

移动或者依据指定的 old_pnew_p 对文件系统对象进行重命名。

  • 如果 old_p 不是文件夹,那么 new_p 就必须为下面几种情况:
    • old_p 相同的文件,或者是它的硬链接:函数啥也不干;
    • 已存在:函数中,首先将 new_p 删除,然后将 new_p 链到 old_p 所指向的文件,最后将 old_p 解连。
    • 该文件不存在,但文件所在的文件夹存在:函数进行正常的移动操作;
  • 如果 old_p 是文件夹,那 new_p 为下面中的几种:
    • old_p 相同的文件夹,或者是它的硬链接:函数啥也不干;
    • 已经存在:正常的移动操作,与前面 old_p 是文件的对应情况类似;
    • 不存在,且不以文件夹分隔符结尾,且其父文件夹存在:与前面的移动操作类似,不再赘述。
  • 操作符号链接:rename 改变的只是符号链接的名称,不是目标对象的。如果 new_p 是一个已经存在的符号链接,那在该函数将把它删除。

以下三种情况中,函数会执行失败:

  • new_p. 或者 .. 结尾;
  • new_p是一个不存在的文件夹,且以文件夹分隔符结尾;
    old_p 是一个文件夹,且为 new_p 的某个上级目录。

案例:

#include <filesystem>#include <fstream>namespace fs = std::filesystem; int main(){ std::filesystem::path p = std::filesystem::current_path() / "sandbox"; std::filesystem::create_directories(p / "from"); std::ofstream{ p / "from/file1.txt" }.put('a'); std::filesystem::create_directory(p / "to"); // fs::rename(p / "from/file1.txt", p / "to/"); // error: "to" is a directory fs::rename(p / "from/file1.txt", p / "to/file2.txt"); // OK // fs::rename(p / "from", p / "to"); // error: "to" is not empty fs::rename(p / "from", p / "to/subdir"); // OK std::filesystem::remove_all(p);}

2.20、std::filesystem::resize_file

void resize_file( const std::filesystem::path& p, std::uintmax_t new_size );void resize_file( const std::filesystem::path& p, std::uintmax_t new_size, std::error_code& ec ) noexcept;

修改常规文件 p 的大小。

如果文件尺寸比新尺寸大,多出来的那部分会被舍弃;

如果文件尺寸比新尺寸小,则文件尺寸将增加,且增加的那部分用 0 填充。

注意:
对支持稀疏文件的系统,增加文件尺寸并不会增加其在文件系统中所占的空间:仅仅在非零数值被写入到文件的时候,其占用的空间才会增加。

案例:
通过在剩余空间中创建稀疏文件来说明

#include <filesystem>#include <fstream>#include <iostream>#include <locale> int main(){ auto p = std::filesystem::temp_directory_path() / "example.bin"; std::ofstream{p}.put('a'); std::cout.imbue(std::locale{"en_US.UTF8"}); std::cout << "File size: " << std::filesystem::file_size(p) << '\n' << "Free space: " << std::filesystem::space(p).free << '\n'; std::filesystem::resize_file(p, 64*1024); // resize to 64 KB std::cout << "File size: " << std::filesystem::file_size(p) << '\n' << "Free space: " << std::filesystem::space(p).free << '\n'; std::filesystem::remove(p);}

输出:

File size: 1Free space: 42,954,108,928File size: 65,536Free space: 42,954,108,928

2.21、std::filesystem::space

std::filesystem::space_info space( const std::filesystem::path& p );std::filesystem::space_info space( const std::filesystem::path& p, std::error_code& ec ) noexcept;

判定 p 所在文件系统的空间信息。其行为类似于 POSIX 的 statvfs

返回值类型中,设定值的方式与 POSIX 结构体 statvfs 的对应关系为:

  • space_info.capacity 将设定为 f_blocks * f_frsize
  • space_info.free 将设定为 f_bfree * f_frsize
  • space_info.available 将设定为 f_bavail * f_frsize
  • 无法判断的就设为 static_cast<std::uintmax_t>(-1)

注意:
space_info.available 可能比 space_info.free 小。

案例:

#include <cstdint>#include <filesystem>#include <iostream> std::uintmax_t disk_usage_percent(const std::filesystem::space_info& si, bool is_privileged = false) noexcept{ if (constexpr std::uintmax_t X(-1); si.capacity == 0 || si.free == 0 || si.available == 0 || si.capacity == X || si.free == X || si.available == X ) return 100; std::uintmax_t unused_space = si.free, capacity = si.capacity; if (!is_privileged) { const std::uintmax_t privileged_only_space = si.free - si.available; unused_space -= privileged_only_space; capacity -= privileged_only_space; } const std::uintmax_t used_space{capacity - unused_space}; return 100 * used_space / capacity;} void print_disk_space_info(auto const& dirs, int width = 14){ (std::cout << std::left).imbue(std::locale("en_US.UTF-8")); for (const auto s : {"Capacity", "Free", "Available", "Use%", "Dir"}) std::cout << "│ " << std::setw(width) << s << ' '; for (std::cout << '\n'; auto const& dir : dirs) { std::error_code ec; const std::filesystem::space_info si = std::filesystem::space(dir, ec); for (auto x : {si.capacity, si.free, si.available, disk_usage_percent(si)}) std::cout << "│ " << std::setw(width) << static_cast<std::intmax_t>(x) << ' '; std::cout << "│ " << dir << '\n'; }} int main(){ const auto dirs = {"/dev/null", "/tmp", "/home", "/proc", "/null"}; print_disk_space_info(dirs);}

输出:

│ Capacity │ Free │ Available │ Use% │ Dir │ 84,417,331,200 │ 42,732,986,368 │ 40,156,028,928 │ 50 │ /dev/null│ 84,417,331,200 │ 42,732,986,368 │ 40,156,028,928 │ 50 │ /tmp│ -1-1-1100 │ /home│ 000100 │ /proc│ -1-1-1100 │ /null

2.22、std::filesystem::status, std::filesystem::symlink_status

std::filesystem::file_status status( const std::filesystem::path& p );std::filesystem::file_status status( const std::filesystem::path& p, std::error_code& ec ) noexcept;std::filesystem::file_status symlink_status( const std::filesystem::path& p );std::filesystem::file_status symlink_status( const std::filesystem::path& p, std::error_code& ec ) noexcept;

前两个函数用于确定 p 指定的文件系统对象的类型与属性

  • 如果 p 是常规文件,函数返回 file_status(file_type::regular, prms)
  • 如果 p 是文件夹,函数返回 file_status(file_type::directory, prms)
  • 如果 p 是块文件,函数返回 file_status(file_type::block, prms)
  • 如果 p 是字符文件,函数返回 file_status(file_type::character, prms)
  • 如果 p 是 fifo 或 pipo 文件,函数返回 file_status(file_type::fifo, prms)
  • 如果 p 是 socket 文件,函数返回 file_status(file_type::socket, prms)
  • 如果 p 是 implementation-defined 文件类型,函数返回 file_status(file_type::A, prms),其中 A 是那种类型的 implementation-defined file_type 常数;
  • 如果 p 不存在,函数返回 file_status(file_type::not_found)
  • 如果 p 存在,但无法确定文件的属性,函数返回 file_status(file_type::unknown)
  • 如果 p 存在,但出错,函数返回 file_status(file_type::none)
  • 其他情况,函数返回 file_status(file_type::unknown, prms)

后两个函数与前两个的功能基本相同,但额外多一个功能:

  • 如果 p 是符号链接,函数返回 file_status(file_type::symlink)

案例:

#include <cstdio>#include <cstring>#include <filesystem>#include <fstream>#include <iostream>#include <sys/socket.h>#include <sys/stat.h>#include <sys/un.h>#include <unistd.h> namespace fs = std::filesystem; void demo_status(const fs::path& p, fs::file_status s){ std::cout << p; // alternative: switch(s.type()) { case fs::file_type::regular: ...} if (fs::is_regular_file(s)) std::cout << " is a regular file\n"; if (fs::is_directory(s)) std::cout << " is a directory\n"; if (fs::is_block_file(s)) std::cout << " is a block device\n"; if (fs::is_character_file(s)) std::cout << " is a character device\n"; if (fs::is_fifo(s)) std::cout << " is a named IPC pipe\n"; if (fs::is_socket(s)) std::cout << " is a named IPC socket\n"; if (fs::is_symlink(s)) std::cout << " is a symlink\n"; if (!fs::exists(s)) std::cout << " does not exist\n";} int main(){ // create files of different kinds fs::create_directory("sandbox"); fs::create_directory("sandbox/dir"); std::ofstream{"sandbox/file"}; // create regular file fs::create_symlink("file", "sandbox/symlink"); mkfifo("sandbox/pipe", 0644); sockaddr_un addr; addr.sun_family = AF_UNIX; std::strcpy(addr.sun_path, "sandbox/sock"); int fd = socket(PF_UNIX, SOCK_STREAM, 0); bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof addr); // demo different status accessors for (auto it{fs::directory_iterator("sandbox")}; it != fs::directory_iterator(); ++it) demo_status(*it, it->symlink_status()); // use cached status from directory entry demo_status("/dev/null", fs::status("/dev/null")); // direct calls to status demo_status("/dev/sda", fs::status("/dev/sda")); demo_status("sandbox/no", fs::status("/sandbox/no")); // cleanup (prefer std::unique_ptr-based custom deleters) close(fd); fs::remove_all("sandbox");}

输出:

"sandbox/file" is a regular file"sandbox/dir" is a directory"sandbox/pipe" is a named IPC pipe"sandbox/sock" is a named IPC socket"sandbox/symlink" is a symlink"/dev/null" is a character device"/dev/sda" is a block device"sandbox/no" does not exist

2.23、std::filesystem::temp_directory_path

为临时文件返回一个临时路径

注意:
在 POSIX 系统中,该路径是通过环境变量 TMPDIRTMPTEMP 以及 TEMPDIR 指定的,如果这些变量没有被设定,则返回默认的路径 /tmp
在 Windows 中,路径是通过函数 GetTempPath 给定的。

path temp_directory_path();path temp_directory_path( std::error_code& ec );

案例:

#include <filesystem>#include <iostream>namespace fs = std::filesystem; int main(){ std::cout << "Temp directory is " << fs::temp_directory_path() << '\n';}

输出:

Temp directory is "C:\Windows\TEMP\"

3、文件类型

is_block_file判断指定的路径是否为 block 设备
is_character_file判断指定的路径是否为 character 设备
is_directory判断指定的路径是否为文件夹
is_empty判断指定的文件或文件夹是否为空
is_fifo判断指定的路径是否为命名管道
is_other判断指定的参数是否为 other 文件
is_regular_file判断指定的参数是否为常规文件
is_socket判断指定的参数是否为命名的 IPC socket
is_symlink判断指定的参数是否为符号链接
status_known检查文件状态是否已知

3.1、std::filesystem::is_block_file

定义于 <filesystem>

检查给定的文件状态或路径是否对应于块特殊文件,如 Linux 上的 /dev/sda/dev/loop0

第一个函数等效于 s.type() == file_type::block

后两个函数等效于 is_block_file(status(p))is_block_file(status(p, ec))

bool is_block_file( std::filesystem::file_status s ) noexcept;bool is_block_file( const std::filesystem::path& p );bool is_block_file( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例:

#include <cstdio>#include <cstring>#include <filesystem>#include <fstream>#include <iostream>#include <sys/socket.h>#include <sys/stat.h>#include <sys/un.h>#include <unistd.h> namespace fs = std::filesystem; void demo_status(const fs::path& p, fs::file_status s){ std::cout << p; // alternative: switch(s.type()) { case fs::file_type::regular: ...} if (fs::is_regular_file(s)) std::cout << " is a regular file\n"; if (fs::is_directory(s)) std::cout << " is a directory\n"; if (fs::is_block_file(s)) std::cout << " is a block device\n"; if (fs::is_character_file(s)) std::cout << " is a character device\n"; if (fs::is_fifo(s)) std::cout << " is a named IPC pipe\n"; if (fs::is_socket(s)) std::cout << " is a named IPC socket\n"; if (fs::is_symlink(s)) std::cout << " is a symlink\n"; if (!fs::exists(s)) std::cout << " does not exist\n";} int main(){ // create files of different kinds fs::create_directory("sandbox"); fs::create_directory("sandbox/dir"); std::ofstream{"sandbox/file"}; // create regular file fs::create_symlink("file", "sandbox/symlink"); mkfifo("sandbox/pipe", 0644); sockaddr_un addr; addr.sun_family = AF_UNIX; std::strcpy(addr.sun_path, "sandbox/sock"); int fd = socket(PF_UNIX, SOCK_STREAM, 0); bind(fd, reinterpret_cast<sockaddr*>(&addr), sizeof addr); // demo different status accessors for (auto it{fs::directory_iterator("sandbox")}; it != fs::directory_iterator(); ++it) demo_status(*it, it->symlink_status()); // use cached status from directory entry demo_status("/dev/null", fs::status("/dev/null")); // direct calls to status demo_status("/dev/sda", fs::status("/dev/sda")); demo_status("sandbox/no", fs::status("/sandbox/no")); // cleanup (prefer std::unique_ptr-based custom deleters) close(fd); fs::remove_all("sandbox");}

输出:

"sandbox/file" is a regular file"sandbox/dir" is a directory"sandbox/pipe" is a named IPC pipe"sandbox/sock" is a named IPC socket"sandbox/symlink" is a symlink"/dev/null" is a character device"/dev/sda" is a block device"sandbox/no" does not exist

3.2、std::filesystem::is_character_file

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::character

后两个函数等效于 is_character_file(status(p))is_character_file(status(p, ec))

bool is_character_file( std::filesystem::file_status s ) noexcept;bool is_character_file( const std::filesystem::path& p );bool is_character_file( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.3、std::filesystem::is_directory

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::directory

后两个函数等效于 is_directory(status(p))is_directory(status(p, ec))

bool is_directory( std::filesystem::file_status s ) noexcept;bool is_directory( const std::filesystem::path& p );bool is_directory( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.4、std::filesystem::is_empty

定义于 <filesystem>

bool is_empty( const std::filesystem::path& p );bool is_empty( const std::filesystem::path& p, std::error_code& ec );

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

第一个函数在底层系统 API 错误上抛出 std::filesystem::filesystem_error,构建时将 p 作为第一个路径参数,将系统错误代码作为错误代码参数。

如果系统 API 调用失败,第二个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例:

#include <cstdio>#include <filesystem>#include <fstream>#include <iostream> int main(){ namespace fs = std::filesystem; const fs::path tmp_dir{fs::temp_directory_path()}; std::cout << std::boolalpha << "Temp dir: " << tmp_dir << '\n' << "is_empty(): " << fs::is_empty(tmp_dir) << '\n'; const fs::path tmp_name{tmp_dir / std::tmpnam(nullptr)}; std::cout << "Temp file: " << tmp_name << '\n'; std::ofstream file{tmp_name.string()}; std::cout << "is_empty(): " << fs::is_empty(tmp_name) << '\n'; file << "cppreference.com"; file.flush(); std::cout << "is_empty(): " << fs::is_empty(tmp_name) << '\n' << "file_size(): " << fs::file_size(tmp_name) << '\n'; file.close(); fs::remove(tmp_name);}

输出:

Temp dir: "/tmp"is_empty(): falseTemp file: "/tmp/fileCqd9DM"is_empty(): trueis_empty(): falsefile_size(): 16

3.5、std::filesystem::is_fifo

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::fifo

后两个函数等效于 is_fifo(status(p))is_fifo(status(p, ec))

bool is_fifo( std::filesystem::file_status s ) noexcept;bool is_fifo( const std::filesystem::path& p );bool is_fifo( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.6、std::filesystem::is_other

定义于 <filesystem>

第一个函数等效于 exists(s) && !is_regular_file(s) && !is_directory(s) && !is_symlink(s)

后两个函数等效于 is_other(status(p))is_other(status(p, ec))

bool is_other( std::filesystem::file_status s ) noexcept;bool is_other( const std::filesystem::path& p );bool is_other( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

3.7、std::filesystem::is_regular_file

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::regular

后两个函数等效于 is_regular_file(status(p))is_regular_file(status(p, ec))

bool is_regular_file( std::filesystem::file_status s ) noexcept;bool is_regular_file( const std::filesystem::path& p );bool is_regular_file( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.8、std::filesystem::is_socket

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::socket

后两个函数等效于 is_socket(status(p))is_socket(status(p, ec))

bool is_socket( std::filesystem::file_status s ) noexcept;bool is_socket( const std::filesystem::path& p );bool is_socket( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.9、std::filesystem::is_symlink

定义于 <filesystem>

第一个函数等效于 s.type() == file_type::symlink

第二和第三个函数等效于 is_symlink(symlink_status(p))is_symlink(symlink_status(p, ec))

bool is_symlink( std::filesystem::file_status s ) noexcept;bool is_symlink( const std::filesystem::path& p );bool is_symlink( const std::filesystem::path& p, std::error_code& ec ) noexcept;

异常:
如果内存分配失败,任何未标记为 noexcept 的重载函数都可能引发 std::bad_alloc

如果系统 API 调用失败,后两个函数会将 std::error_code& 参数设置为系统 API 错误代码;如果未出现错误,则执行 ec.clear()

案例见 std::filesystem::is_block_file

3.10、std::filesystem::status_known

定义于 <filesystem>

s.type() != file_type::none 相同,用于判断给定的 file_status 是否已知

bool status_known( std::filesystem::file_status s ) noexcept;

注意:
不管名称如何,该函数都会检查文件状态 file_type::none(即发生错误),而不是 file_type::unknown(即文件存在,但无法确定其类型)。

C++17 filesystem 库 学习笔记-CSDN博客 (2024)

References

Top Articles
The UPS Store | Ship & Print Here > 34428 Yucaipa Blvd
Is stores.yoshinoya.com betrouwbaar? Reviews en ervaringen
Shining Time Station (television series)
5 Anterior Pelvic Tilt Exercises
La Qua Brothers Funeral Home
Julia Is A Doctor Who Treats Patients
Chelsea Marie Boutique
1 Bedroom Apartment For Rent Private Landlord
Scholar Dollar Nmsu
Twitchxx.com
Shahala Middle School Shahala Middle School Student Handbook
Faotp Meaning In Text
Tinyzonetv.to Unblocked
Iapd Lookup
Unit 8 Lesson 2 Coding Activity
Ar Kendrithyst
Rs3 Ranged Weapon
Nwi Police Blotter
Nissan Rogue Tire Size
Costco Gas Price City Of Industry
Theater X Orange Heights Florida
T-Zell-Leukämie mit großen granulären Lymphozyten - Altmeyers Enzyklopädie - Fachbereich Innere Medizin
Healthstream Mobile Infirmary
Mybackpack Bolles
Megan Hall Bikini
Theatervoorstellingen in Roosendaal, het complete aanbod.
8.7 Increase Of 841
Ulta Pigeon Forge
8004966305
Fanart Tv
10 Best Laptops for FL Studio in 2023 | Technize
Boise Craigslist Cars And Trucks - By Owner
Herbalism Guide Tbc
Chalupp's Pizza Taos Menu
Mygxo Gxo Com Employee Login
Metalico Sharon Pa
Dan And Riya Net Worth In 2022: How Does They Make Money?
La Monja 2 Pelicula Completa Tokyvideo
SYSTEMAX Software Development - PaintTool SAI
Latest News & Breaking News Coverage | Flipboard
Used Cars for Sale in Phoenix, AZ (with Photos)
Pre-Order Apple Watch Series 10 – Best Prices in Dubai, UAE
Apartments for Rent in Atlanta, GA - Home Rentals | realtor.com®
Melissa Bley Ken Griffin
Bretnie Hall Ashland Ky
Busted Newspaper Zapata Tx
Doctor Strange in the Multiverse of Madness - Wikiquote
Jeff Buley Obituary
Niw 一亩三分地
Eugenics Apush
Lenscrafters Westchester Mall
Latest Posts
Article information

Author: Greg O'Connell

Last Updated:

Views: 5880

Rating: 4.1 / 5 (62 voted)

Reviews: 93% of readers found this page helpful

Author information

Name: Greg O'Connell

Birthday: 1992-01-10

Address: Suite 517 2436 Jefferey Pass, Shanitaside, UT 27519

Phone: +2614651609714

Job: Education Developer

Hobby: Cooking, Gambling, Pottery, Shooting, Baseball, Singing, Snowboarding

Introduction: My name is Greg O'Connell, I am a delightful, colorful, talented, kind, lively, modern, tender person who loves writing and wants to share my knowledge and understanding with you.