Как заставить std :: filesystem :: directory_iterator перечислять имена файлов по порядку - PullRequest
0 голосов
/ 16 июня 2020

Я пытаюсь получить имена файлов в каталоге «по порядку». Я попытался сделать это с помощью c ++ std :: filesystem :: directory_iterator. Как упоминалось в https://en.cppreference.com/w/cpp/filesystem/directory_iterator, он предоставляет все имена файлов в каталоге, за исключением "." и оператор "..", но не по порядку.

Пожалуйста, помогите мне, заранее спасибо.

Вот простой код, который я использовал

#include <iostream>
#include <string>
#include <experimental/filesystem>
#include <vector>

int main 
{
  // path to cereal folder 
  std::string path_to_cereal_folder = "/home/ros2/Documents";

  for (auto& entry : std::experimental::filesystem::directory_iterator(path_to_cereal_folder) )
  {
      std::cout << entry.path() << std::endl;     
  }
  return 0;
}

1 Ответ

0 голосов
/ 16 июня 2020

Как указано в ссылке, итератор не имеет порядка. Если вы хотите распечатать файлы в каком-то порядке, вы должны использовать другие контейнеры.


Печать в алфавитном порядке

Необходимые шаги:

  1. Перебирать файлы и вставлять имена файлов в set
  2. Перебрать (отсортированный) set и распечатать имена файлов. Записи в наборе сортируются автоматически.

Я адаптировал ваш код и пришел к этому решению:

#include <iostream>
#include <filesystem>
#include <set>

//--------------------------------------------------------------------------//
using namespace std;
namespace fs = std::filesystem;

//--------------------------------------------------------------------------//
int main() {
  string path_name = "/bin";

  //--- filenames are unique so we can use a set
  set<fs::path> sorted_by_name;

  for (auto &entry : fs::directory_iterator(path_name))
    sorted_by_name.insert(entry.path());

  //--- print the files sorted by filename
  for (auto &filename : sorted_by_name)
    cout << filename.c_str() << endl;
}

Печать с сортировкой по отметке времени

Шаги, которые необходимо предпринять:

  1. Перебирать файлы и извлекать метку времени
  2. Вставлять файлы на карту, используя метку времени в качестве ключа сортировки
  3. Перебирать ( sorted) map и распечатать имена файлов и метку времени, преобразованную во что-то полезное.

Вспомогательная функция для преобразования метки времени в удобочитаемое время была взята из здесь .

#include <iostream>
#include <filesystem>
#include <chrono>
#include <map>

//--------------------------------------------------------------------------//
using namespace std;

//--------------------------------------------------------------------------//
//--- helper function convert timepoint to usable timestamp
template <typename TP>
time_t to_time_t(TP tp) {
  using namespace chrono;
  auto sctp = time_point_cast<system_clock::duration>(tp - TP::clock::now() + system_clock::now());
  return system_clock::to_time_t(sctp);
}

//--------------------------------------------------------------------------//
namespace fs = std::filesystem;
int main()
{
  string path_name = "/bin";
  map<time_t, fs::directory_entry> sort_by_time;

  //--- sort the files in the map by time
  for (auto &entry : fs::directory_iterator(path_name))
    if (entry.is_regular_file()) {
      auto time = to_time_t(entry.last_write_time());
      sort_by_time[time] = entry;
    }

  //--- print the files sorted by time
  for (auto const &[time, entry] : sort_by_time) {
    string timestamp = asctime(std::localtime(&time));
    timestamp.pop_back(); // remove automatic linebreak
    cout << timestamp << "\t " << entry.path().c_str() << endl;
  }
}

Печать с сортировкой по размеру файла

Шаги, которые необходимо предпринять:

  1. Перебирать файлы и извлекать размер файла
  2. Вставить файлы на карте с размером файла в качестве ключа сортировки
  3. Перебрать (отсортированный) map и распечатать имена файлов и размер файла, преобразованный во что-то полезное.

Помощник функция для преобразования файла в читаемый Информация была взята из cpp -ссылки .

#include <iostream>
#include <filesystem>
#include <map>
#include <cmath>

//--------------------------------------------------------------------------//
using namespace std;
namespace fs = std::filesystem;

//--------------------------------------------------------------------------//
//--- helper function convert the filesize into something meaningful
struct HumanReadable { uintmax_t size {}; }; 
template <typename Os> Os& operator<< (Os& os, HumanReadable hr) {
    int i{};
    double mantissa = hr.size;
    for (; mantissa >= 1024.; ++i) {
        mantissa /= 1024.;
    }
    mantissa = std::ceil(mantissa * 10.) / 10.;
    os << mantissa << "BKMGTPE"[i];
    return i == 0 ? os : os << "B (" << hr.size << ')';
}

//--------------------------------------------------------------------------//
int main() {
  string path_name = "/bin";
  map<uintmax_t, fs::directory_entry> sort_by_size;

  //--- sort the files in the map by size
  for (auto &entry : fs::directory_iterator(path_name))
    if (entry.is_regular_file()) {
      auto size = entry.file_size();
      sort_by_size[size] = entry;
    }

  //--- print the files sorted by size
  for (auto const &[size, entry] : sort_by_size)
    cout << HumanReadable{size} << "\t " << entry.path().c_str() << endl;  
}
...