Вот код, который я использовал для его проверки.
Он работает на обычных каталогах, но не на тех, которые смонтированы под sshfs.
Моя цель — использовать эти методы в
https://github.com/jlettvin/Greased-Grep
который предназначен для глобального нечеткого поиска
ключевые слова, которые должны присутствовать и ключевые слова, которые должны отсутствовать.
#include <iostream>
#include <string>
#include <functional>
#include <dirent.h>
using std::cout;
using std::endl;
using std::string;
using std::function;
bool neither (const char* path)
{
bool ret = (path != nullptr);
if (ret)
{
if (path[0] == '.')
{
if (path[1] == '\0') ret = false;
if (path[1] == '.' && path[2] == '\0') ret = false;
}
}
return ret;
}
void walk (const string &path, function<void (const string &)> talk)
{
if (auto dir = opendir (path.c_str ())) {
while (auto f = readdir (dir)) {
auto name = f->d_name;
auto type = f->d_type;
if (neither (name))
{
switch (type)
{
case DT_DIR: walk (path + name + "/", talk); break;
case DT_REG: talk (path + name ); break;
}
}
}
closedir(dir);
}
}
int main (int argc, char** argv)
{
walk ("./", [](const string &path) { cout << path << endl; });
return 0;
}
Вам нужно просмотрите следующую документацию в Linux readdir(3)
страница справочника:
unsigned char d_type; /* Type of file; not supported by all filesystem types */
В частности, ваше внимание направлено на часть «не поддерживается всеми типами файловых систем».
Ваш код ожидает d_type
установить. Тем не мение, readdir(3)
не гарантирует, что это будет.
Одно из возможных значений для d_type
является:
DT_UNKNOWN The file type could not be determined.
Код, который должен быть подготовлен для обработки всех возможностей, должен явно проверять DT_UNKNOWN
и, если да, добавить d_name
на имя каталога, stat()
имя файла, а затем получить тип файла оттуда.
d_type
это ярлык Если это установлено, замечательно. У вас это есть сразу. Если нет, вам придется работать, чтобы получить его.
sshfs
очевидно, не поддерживает возвращение d_type
от readdir(3)
, С надеждой, sshfs
инвентарь stat()
,
P.S., не то, что кроме каталога и обычных файлов, есть также несколько других специальных типов, с которыми вы можете или не можете обращаться (при условии, что sshfs
могу даже предоставить их вам). Это то, что вам нужно исследовать самостоятельно.
У меня есть код, который я хотел работать.
После масштабных экспериментов со всей чувствительностью ко всевозможным флагам, условиям и ситуациям я решил пойти с предельной простотой.
Я отношусь ко всему найденному как к каталогу, так и к файлу. Если это не каталог, я обнаруживаю и игнорирую все ошибки и продолжаю. Если это каталог, я открываю его и ищу в нем то, что хочу. Это преимущество в Greased-Grep, цель которого — найти подходящие вещи. Имена файлов — это такие же вещи, как и их содержимое.
Итак, мой ответ: мне плевать на неудачи. Меня волнуют только успехи, поэтому я отказываюсь от неудач без каких-либо испытаний.
Это прекрасно работает, когда спускаются каталоги, смонтированные по sshfs.
Любой, кто интересуется, как выглядит этот код, может подписаться на мой github:
https://github.com/jlettvin/Greased-Grep/blob/master/gg.cpp
Вот выдающийся код:
void walk (const string& a_path)
{
// Don't attempt to assess validity of filenames... just fail.
// Treat directories like files and search filenames in directories.
// This enables gg to work on sshfs mounted filesystems.
auto d{a_path};
auto s{d.size ()};
if (s && d[s - 1] == '/') d.resize (s-1);
errno = 0;
if (auto dir = opendir (d.c_str ()))
{
while (!errno)
{
if (auto f = readdir (dir))
{
if (auto p = f->d_name)
{
if (auto q = p)
{
if (!(*q++ == '.' && (!*q || (*q++ == '.' && !*q))))
{
auto e = d + "/" + p;
walk (e);
mapped_search (e.c_str ());
errno = 0;
}
}
else break;
}
else break;
}
else break;
}
}
}