POSIX Программа для поиска файлов во всей файловой системе - PullRequest
2 голосов
/ 27 апреля 2011

Привет всем. Мне нужно написать программу POSIX для поиска во всей файловой системе указанного файла, начиная с верхнего каталога. У меня есть некоторый код, который вообще не делается, но когда я запускаю его и проверяю, является ли определенный файл каталогом, он говорит, что этот файл, который вообще не является каталогом, является каталогом и пытается перейти в него, вызывая ошибку. Я не уверен, как я могу сказать, что этот тип файла не является каталогом.

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

Файл, о котором идет речь, - / dev / dri / card0, и я запускаю его с виртуальной машины Debian.

#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <unistd.h>
#include <time.h>
#include <stdint.h>
#include <locale.h>
#include <langinfo.h>
#include <fcntl.h>
#include <iostream>
#include <stdio.h>
#include <string>
using namespace std; 

void SearchDirectory(string file_Name, string directory){
    string new_Directory = directory; 
    DIR *dirp; 
    dirp = opendir(directory.c_str()); 
    struct dirent *dptr; 
    struct stat statStruct; 

    while(dptr = readdir(dirp)){
        stat(dptr->d_name, &statStruct); 
        if( S_ISDIR(statStruct.st_mode) ){

            string check = dptr->d_name; 
            if ( check.compare(".") == 0 || check.compare("..") == 0 ){
                continue; 
            }
            else{
                cout << dptr->d_name << " is is a directory" << endl; 
                new_Directory.append("/");
                new_Directory.append(dptr->d_name);  
                SearchDirectory(file_Name, new_Directory); 
            }
        }
        else if( S_ISREG(statStruct.st_mode)){
            string check = dptr->d_name; 
            if( check.compare(file_Name) == 0){
                cout << "Found " << file_Name << " in " << directory << "/" << endl; 
            }
        }
    }
}

int main(int argc, char *argv[]){

    if(argc < 2 || argc > 2){
        cerr << "This program will find the specified file." << endl; 
        cerr << "Usage: mysearch <filename>" << endl; 
        return 1; 
    }

    string file_Name = argv[1]; 
    SearchDirectory(file_Name, "/"); 

    return 0; 

}

Ответы [ 7 ]

4 голосов
/ 27 апреля 2011

POSIX.2 требует рабочую команду "найти".

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>

int main(int argc, char **argv)
{
    if (argc != 2) {
        fprintf(stderr, "Usage: %s <filename>", argv[0]);
    }

    execlp("find", "find", "/", "-name", argv[1], "-print", (char *)NULL);
    exit(EXIT_FAILURE);
}
2 голосов
/ 28 апреля 2011

Не в пользу ОП, который пишет «Суть в том, чтобы придумать способ сделать это сам», а скорее в интересах потомков, вот способ использования Boost.Filesystem :

#include <boost/filesystem.hpp>
namespace fs = boost::filesystem;

// sample usage: find_file("/home", ".profile");
void find_file( const fs::path& dirPath, const std::string& fileName) {
  fs::recursive_directory_iterator end;
  for(fs::recursive_directory_iterator it(dirPath); it != end; ++it) {
    if(it->leaf() == fileName)
      std::cout << it->path() << "\n";
    if(fs::is_symlink(it->symlink_status()))
      it.no_push();
  }
}
2 голосов
/ 27 апреля 2011

->d_name возвращает только имя файла, а не путь к файлу.Вам нужно иметь стат (еще не построенный) new_Directory вместо dptr->d_name.

У вас также есть проблема, если каталог содержит более одного подкаталога.Ваша конструкция new_Directory неверна для каждого подкаталога после первого.

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

void SearchDirectory(string directory, string target_File_Name){
    DIR *dirp = opendir(directory.c_str());
    if (!dirp) {
        perror(("opendir " + directory).c_str());
        return;
    }

    struct dirent *dptr;
    while(dptr = readdir(dirp)){
        string file_Name = dptr->d_name;
        string file_Path = directory + "/" + file_Name;

        struct stat statStruct; 
        stat(file_Path.c_str(), &statStruct); 
        if( S_ISDIR(statStruct.st_mode) ){
            if ( file_Name.compare(".") == 0 || file_Name.compare("..") == 0 ){
                continue; 
            }

            SearchDirectory(file_Path, target_File_Name);
        }
        else if( S_ISREG(statStruct.st_mode)){
            if( file_Name.compare(target_File_Name) == 0){
                cout << file_Path << endl;
            }
        }
    }

    closedir(dirp);
}

Обновление : добавлена ​​вторая проблема.

Обновление : добавлена ​​третья проблема.

Обновление : добавлен код.

1 голос
/ 28 апреля 2011

Поскольку C ++ является опцией, почему бы не использовать что-то вроде Boost.Filesystem ? В двухминутном учебнике Boost.Filesystem приведен пример реализации поиска с использованием итераторов каталогов .

1 голос
/ 27 апреля 2011

Ваша проблема заключается в том, чтобы "найти дерево для поиска совпадений"

BFS и DFS - это основные канонические алгоритмы.Дайте им стартовый узел и уходите.

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

Вы должны быть в состоянии сопоставить каждую точку в алгоритмах * FS с операцией каталога.

1 голос
/ 27 апреля 2011

Я не уверен, что это POSIX или нет, но функция библиотеки nftw широко доступна в UNIX (HP-UX, AIX, Linux).

1 голос
/ 27 апреля 2011

Использовать fork, execv и реализованный в Unix процесс / usr / bin / find и перенаправлять его вывод в область результатов?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...