使用boost :: filesystem以数字方式对目录的子文件夹和文件名进行排序

时间:2017-09-04 15:10:16

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

我使用与boost tutorials中相同的示例。但是因为我的文件名被编号(1,20,23,..)。代码无法比较字符串(例如20< 7)。有没有办法在数字上比较directory_iteration。这是代码的片段

<div class="row">
  <div class="col">
    This is front part
    <div class="back">This is back part</div>
  </div>
  <div class="col">
    This is front part
    <div class="back">This is back part</div>
  </div>
  <div class="col">
    This is front part
    <div class="back">This is back part</div>
  </div>
</div>

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

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';
        }
      }

1 个答案:

答案 0 :(得分:2)

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

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

方法1:

存储文件名和数值对,在填充向量时解析。

方法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";
    }
}