C ++ Рекурсивное сканирование файлов / каталогов с использованием Cygwin - PullRequest
0 голосов
/ 22 мая 2009

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

Для этого я пытаюсь использовать cygwin для моего компилятора, используя dirent.h и шаблон:

#include <dirent.h> 
#include <stdio.h> 

int main(void)
{
  DIR           *d;
  struct dirent *dir;
  d = opendir(".");
  if (d)
  {
    while ((dir = readdir(d)) != NULL)
    {
      // Stuff
    }    
    closedir(d);
  }    
  return(0);
}

Но нужно также добавить рекурсивный поиск в каталогах. Чтобы сделать это, я решил попробовать opendir () для следующего файла и определить код ошибки, чтобы определить, был ли он успешно открыт как каталог (который я затем рекурсивно использовал) или он был возвращен как «not». каталог », который затем будет указан как просто файл.

Я признаю, что это очень круто, но я не смог найти лучший метод, который мог бы сохранить некоторую переносимость (не win32), даже после нескольких часов поиска.

Итак, мое упрощенное решение (немного псевдо для простоты) выглядит примерно так:

int scan(string startdir)
{
  DIR           *d;
  struct dirent *dir;
  d = opendir(startdir.cstr());
  if (d)
  {
    while ((dir = readdir(d)) != NULL)
    {
      if( NOT '.' AND NOT '..')
      {
        if(temp = opendir(startdir + d) == NULL)
        {
           //FILE OR ERROR
        }else{
          //Opened successfully as a directory, so recurse
          scan(startdir + d->d_name + "\\");
        }
      }
    }
    closedir(d);
  }
  return(0);
}

Это просто наполовину переписанный код psuedo, чтобы сделать его простым, но, похоже, он работает (хотя я очень открыт для предложений о лучших способах сделать это).

Однако основная проблема, с которой я сталкиваюсь, - это конкретный файл ссылок 'c: \ cygwin \ dev \ fd', который, кажется, открывается как каталог и рекурсивно открывается снова и снова бесконечно.

Файл 'fd' имеет размер 4 КБ, 106 байт без расширения и является ярлыком, который не указывает нигде в Windows.

Эта ошибка указывает на то, что либо этот метод kludgey содержит ошибки, либо есть проблема в реализации cygwin, в которой я компилирую.

В качестве краткого примера:

Error Reading: c:\cygwin\dev\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\5\fd\0 No such file or directory

Исключая этот каталог, поиск, кажется, работает хорошо. Но я не в порядке с жестким кодированием исключения в сканере.

Если у кого-либо есть какие-либо идеи, предложения, решения или альтернативные методы решения этой проблемы, ваш вклад будет принят.

Спасибо.

Ответы [ 6 ]

1 голос
/ 26 мая 2009

Похоже, виновником является то, что файл fd ссылается на / proc /

Я не гарантирую, что это правда, но у меня сложилось впечатление, что это позволяет сканеру рекурсивно проходить по своей собственной структуре каталогов.

Поначалу мои попытки с помощью readlink () решить эту проблему были многообещающими, но я обнаружил, что при более глубоких уровнях сканирования это становится ненадежным, и ошибки все еще могут возникать.

Сейчас я ищу другие способы достижения этой функциональности (например, boost :: filesystem).

1 голос
/ 22 мая 2009

Если вы можете использовать boost, рассмотрите возможность использования boost :: filesystem . Учебники включают в себя простую программу ls, которую вы можете легко расширить для рекурсивной работы. Библиотека также включает методы для запроса типов файлов, которые, вероятно, могут решить вашу конкретную проблему.

0 голосов
/ 25 января 2012

В вашем примере вы попытались снова использовать opendir (), чтобы определить, является ли что-то файлом или каталогом. Вы можете сделать это более напрямую, используя stat () из "sys / stat.h". Это также должно быть доступно в Cygwin. Вы можете использовать макросы S_ISREG () и S_ISDIR () для проверки наличия обычного файла или каталога. Вероятно, что-то вроде этого:

    struct stat *buf = new struct stat;
    if(!stat(d->d_name, buf))
    {
        if(S_ISREG(buf->st_mode))
        {
            std::cout << "    File: " << entry->d_name << "\n";
        }
        if(S_ISDIR(buf->st_mode) &&  

Пожалуйста, посмотрите также ответ , который я поставил на другой вопрос .

0 голосов
/ 28 мая 2009

В библиотеке cygwin есть и ftw (), и fts (), используйте один из них.

0 голосов
/ 23 мая 2009

Вы понимаете, что в cygwin есть все инструменты UNIX.

Найти очень полезно.

0 голосов
/ 22 мая 2009

Это виртуальная файловая система, возможно с символическими ссылками. Cygwin поддерживает символические ссылки, и вам, возможно, придется учесть это.

...