c++ - 使用 boost::filesystem 对目录的子文件夹和文件名进行数字排序

标签 c++ c++11 boost boost-filesystem

我使用与 boost tutorials 中相同的示例。但由于我的文件名已编号(1,20,23,..)。该代码无法比较字符串(例如 20 < 7)。有没有办法以数字方式比较directory_iteration。这是代码片段

else if (is_directory(p))      // is p a directory?
      {
        cout << p << " is a directory containing:\n";

        typedef vector<path> vec;             // store paths,
        vec v;                                // so we can sort them later

        copy(directory_iterator(p), directory_iterator(), back_inserter(v));

        sort(v.begin(), v.end());             //  **I want to sort this numerically**

        for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it)
        {
          cout << "   " << *it << '\n';
        }
      }

目录和子文件夹的布局如下所示:

root/
    1/
     1.bmp
     2.bmp
     3.bmp
     4.bmp
     ...
    2/
     1.bmp
     2.bmp
     3.bmp
     4.bmp
    ....
    3/
     1.bmp
     2.bmp
     3.bmp
     4.bmp
     ....

最佳答案

由于您无法将文件名的格式更改为可排序,因此您需要自己进行一些处理 - 解析每个文件名中的数字,并将其用于排序。

我想到了两种方法,在内存和 CPU 使用率之间进行权衡。

方法一:

存储文件名和数值对,在填充 vector 时进行解析。

方法 2:

仅存储路径并在比较期间执行转换。


代码:

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <iostream>

namespace fs = boost::filesystem;

int parse_filename(fs::path const& p)
{
    return std::stoi(p.filename().string());
}

void sort_numeric_1(fs::path const& p)
{
    typedef std::pair<fs::path, int> file_entry;
    typedef std::vector<file_entry> vec;
    vec v;

    for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) {
        v.emplace_back(*it, parse_filename(*it));
    }

    std::sort(v.begin(), v.end()
        , [](file_entry const& a, file_entry const& b) {
        return a.second < b.second;
    });

    for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) {
        std::cout << "   " << it->first << '\n';
    }
}

void sort_numeric_2(fs::path const& p)
{
    typedef std::vector<fs::path> vec;
    vec v;

    std::copy(fs::directory_iterator(p), fs::directory_iterator(), back_inserter(v));

    std::sort(v.begin(), v.end()
        , [](fs::path const& a, fs::path const& b) {
        return std::stoi(a.filename().string()) < std::stoi(b.filename().string());
    });

    for (vec::const_iterator it(v.begin()), it_end(v.end()); it != it_end; ++it) {
        std::cout << "   " << *it << '\n';
    }
}

int main()
{
    sort_numeric_1("test");
    std::cout <<"\n";
    sort_numeric_2("test");
}

目录内容:

> ls test
1.txt  10.txt  127.txt  20.txt  23.txt

输出:

"test\1.txt"
"test\10.txt"
"test\20.txt"
"test\23.txt"
"test\127.txt"

"test\1.txt"
"test\10.txt"
"test\20.txt"
"test\23.txt"
"test\127.txt"

更新它以处理您所显示的整个目录结构,您可能会得到如下内容:

  • 首先找到所有目录,并按数字排序
  • 然后对每个找到的目录中的文件进行排序
  • 合并所有已排序的文件列表

示例:

#include <boost/filesystem/path.hpp>
#include <boost/filesystem/operations.hpp>
#include <iostream>

namespace fs = boost::filesystem;

typedef std::vector<fs::path> path_vec;

void sort_numeric(path_vec& v)
{
    std::sort(v.begin(), v.end()
        , [](fs::path const& a, fs::path const& b) {
        return std::stoi(a.filename().string()) < std::stoi(b.filename().string());
    });
}

path_vec sort_root_dir(fs::path const& p)
{
    path_vec dirs;

    for (fs::directory_iterator it(p); it != fs::directory_iterator(); ++it) {
        if (is_directory(*it)) {
            dirs.emplace_back(*it);
        }
    }

    sort_numeric(dirs);

    path_vec files;
    for (path_vec::const_iterator it(dirs.begin()), it_end(dirs.end()); it != it_end; ++it) {
        path_vec dir_files;
        std::copy(fs::directory_iterator(*it), fs::directory_iterator(), back_inserter(dir_files));
        sort_numeric(dir_files);
        files.insert(files.end(), dir_files.begin(), dir_files.end());
    }

    return files;
}

int main()
{
    path_vec files = sort_root_dir("test");

    for (auto const& f : files) {
        std::cout << f << "\n";
    }
}

关于c++ - 使用 boost::filesystem 对目录的子文件夹和文件名进行数字排序,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46039890/

相关文章:

c++ - 使用 gcc 编译内联汇编时出错, "shl"

boost - 输出 BGL 边权重

c++ - 了解 boost 执行器示例

c - 什么时候可以将原子读取-修改-写入操作分解为组成宽松的操作+屏障?

ios - 如何为 iPhone (ARM) 构建 boost 1.56.0 boost::context

c++ - 函数指针如何替代 switch 语句?

c++ - Linux C++ 应用程序文件保护

c++ - 如何组织复杂程序的资源?

c++ - 如何做一个常量对象的工厂

c++ - 在 Visual Studio 中解决忽略的 constexpr?