【问题标题】:How to get the largest files in the current working directory in unix?如何在unix中获取当前工作目录中最大的文件?
【发布时间】:2019-08-26 20:03:43
【问题描述】:

我知道如何在 Unix 中获取文件列表。我试过的c++程序如下。现在如何按降序打印最大的文件?

int main() {
    DIR* drstrm = opendir(".");

    if (drstrm == NULL) {
        perror("error opening directory");
        return 1;
    }

    struct dirent* directoryentry = readdir(drstrm);

    while (directoryentry != NULL) {
        cout << (*directoryentry).d_name << endl;
        directoryentry = readdir(drstrm);
    }

    return 0;
}

【问题讨论】:

  • 可以使用C++17标准文件系统库吗?
  • (*foo).bar 通常写成foo-&gt;bar,顺便说一句。
  • 我并不一定打算将它作为一个链接的完全副本关闭,但它会自动完成。 :-/ 无论如何,readdir() does not specify an order。我要指出的方向就是这基本上是“您需要将信息放入结构中并对其进行排序”。因此,您的问题不是关于文件,而是一个更简单的问题,例如“我如何制作/排序列表”——对此有很多研究答案。
  • 我只是想对 IS_REG 为 true 的文件执行此操作。知道如何为这些特定文件执行此操作吗?
  • 是的,你可以@shawn。

标签: c++ unix


【解决方案1】:

为此,您必须将文件信息读入数据结构(如std::vector),然后根据文件大小对文件信息进行排序。

老式的方法可能是这样的:

DIR* drstrm = opendir(".");

if(drstrm == NULL)
    throw std::runtime_error(std::strerror(errno));

struct stat st; // this is to use decltype

// keep info from dirent & stat in one place
struct file_info
{
    std::string name;
    decltype(st.st_size) size;
};

// store list of files here to be sorted
std::vector<file_info> files;

while(dirent* entry = readdir(drstrm))
{
    // get file info
    if(::stat(entry->d_name, &st) == -1)
        throw std::runtime_error(std::strerror(errno));

    // is it a regular file?
    if(!S_ISREG(st.st_mode))
        continue;

    // store it ready for sorting
    files.push_back({entry->d_name, st.st_size});
}

// sort the file_info objects according to size
std::sort(std::begin(files), std::end(files), [](file_info const& a, file_info const& b){
    return a.size < b.size;
});

// print them out
for(auto const& file: files)
    std::cout << file.name << ": " << file.size << '\n';

幸运的是,在较新版本的 C++ (C++17) 中,您可以使用新的 &lt;filesystem&gt; 标准库:

namespace fs = std::filesystem; // for brevity

std::vector<fs::path> files;

for(auto const& ent: fs::directory_iterator("."))
{
    if(!fs::is_regular_file(ent))
        continue;

    files.push_back(ent);
}

std::sort(std::begin(files), std::end(files), [](fs::path const& a, fs::path const& b){
    return fs::file_size(a) < fs::file_size(b);
});

for(auto const& file: files)
    std::cout << file << ": " << fs::file_size(file) << '\n';

【讨论】:

    【解决方案2】:

    既然你说你可以使用 C++17,它引入的文件系统库使这变得非常容易(并且可移植到没有 opendir()/readdir() 的系统):

    #include <iostream>
    #include <vector>
    #include <filesystem>
    #include <algorithm>
    #include <string>
    
    int main(int argc, char **argv) {      
      if (argc != 2) {
        std::cerr << "Usage: " << argv[0] << " DIRECTORY\n";
        return 1;
      }
    
      std::vector<std::filesystem::directory_entry> files;
    
      for (const auto &dirent : std::filesystem::directory_iterator(argv[1])) {
        if (dirent.is_regular_file()) {
          files.push_back(dirent);
        }
      }
    
      std::sort(files.begin(), files.end(), [](const auto &a, const auto &b){
          return a.file_size() > b.file_size(); });
    
      for (const auto &dirent : files) {
        // Quotes the filenames
        // std::cout << dirent.path() << '\n';
        // Doesn't quote
        std::cout << static_cast<std::string>(dirent.path()) << '\n';
      }
    
      return 0;
    }
    

    用法:

    $ g++-8 -std=c++17 -O -Wall -Wextra test.cpp -lstdc++fs
    $ ./a.out .
    a.out
    bigfile.txt
    test.cpp
    smallfile.txt
    etc.
    

    如果你不能使用 C++17,同样的方法仍然适用:将文件名和它们的大小放在一个向量中,并使用&gt;而不是普通的&lt;(其中将从最小到最大排序)。在 POSIX 系统上,您可以使用 stat(2) 获取文件大小。

    【讨论】:

    • 在你的输出语句中不需要强制转换 dirent.path().string() 会很好。
    猜你喜欢
    • 2013-06-26
    • 2018-04-17
    • 2011-06-19
    • 2021-01-18
    • 2015-09-02
    相关资源
    最近更新 更多