在类似于 c++ for Linux 中的 statfs 命令的变量中获取目录空间的命令

问题描述

我知道 statfs 在传递给它的缓冲区中返回有关已安装文件系统的信息。我需要一个类似的内置函数来在将目录路径传递给它时获取目录的空间。有人可以帮我解决这个问题吗? TIA!

解决方法

标准的 C++17 解决方案可能是累积目录和子目录中的文件大小。

示例:

#include <cstdint>
#include <deque>
#include <filesystem>
#include <iostream>
#include <string_view>

int cppmain(std::string_view program,std::deque<std::filesystem::path> dirs) {
    if(dirs.empty()) {
        std::cout << "USAGE: " << program << " <directories...>\n";
        return 1;
    }

    std::error_code ec; // for checking errors
    // Generic end-of-dir iterator:
    std::filesystem::directory_iterator end{};

    std::uintmax_t result = 0; // the sum of all file sizes

    do {
        // get the first directory in the deque
        std::filesystem::path dir = std::move(dirs.front());
        dirs.pop_front();

        // loop over all the directory entries in the directory
        for(std::filesystem::directory_iterator dit(dir,ec);
            dit != end; ++dit) 
        {
            if(dit->is_symlink()) {
                std::cerr << "Skipping symlink " << *dit << '\n';

            } else if(dit->is_directory(ec)) {
                // put the directory in the deque to examine later
                dirs.emplace_back(dit->path());

            } else if(dit->is_regular_file(ec)) {
                // a regular file - add its size to the result
                result += dit->file_size();

            } else {
                // if you want to log files you can't check:
                std::cerr << "Unknown size " << *dit << '\n';
            }
        }
        // loop for as long as there are directories in the deque:
    } while(not dirs.empty());

    std::cout << result << '\n';
    return 0;
}

int main(int argc,char* argv[]) {
    // Put all the arguments (except argv[0]) in
    // "std::deque<std::filesystem::path> dirs":
    return cppmain(argv[0],{argv + 1,argv + argc});
}

statfs(2) 替换可能类似于以下内容 - 但它提供的详细信息不如 statfs()

#include <filesystem>
#include <iostream>

int main(int argc,char* argv[]) {
    if(argc != 2) {
        std::cout << "USAGE " << argv[0] << " <directory>\n";
        return 1;
    }

    std::error_code ec;
    std::filesystem::path path(argv[1]);
    std::filesystem::space_info si = std::filesystem::space(path,ec);
    if(ec) {
        std::cerr << "Error: " << path << ": " << ec.message() << '\n';
        return 1;
    }

    std::cout << "capacity : " << si.capacity << '\n'
              << "free     : " << si.free << '\n'
              << "available: " << si.available << '\n';
}