POSIX程序在整个文件系统中搜索文件

时间:2011-04-27 19:29:12

标签: c++ c posix

嘿大家好我需要编写一个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 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:2)

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

更新:添加了第二个问题。

更新:添加了第三个问题。

更新:添加了代码。

答案 2 :(得分:2)

不是为了OP的利益,他写道“关键在于提出一种方法来做到这一点”,而是为了后代的利益,这里有一种方法可以使用Boost.Filesystem:< / p>

#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();
  }
}

答案 3 :(得分:1)

使用forkexecv和Unix实现的/ usr / bin / find过程并将其输出重定向到结果区域?

答案 4 :(得分:1)

我不确定它是否是POSIX,但nftw库函数在UNIX(HP-UX,AIX,Linux)上广泛使用。

答案 5 :(得分:1)

您的问题是“搜索树匹配”

BFS和DFS是规范的基本算法。给他们一个开始节点然后去。

如果你按照符号链接,你会遇到麻烦;所以要对它们进行测试,不要跟随它们。

您应该能够将* FS算法中的每个点映射到目录操作。

答案 6 :(得分:1)

由于C ++是一个选项,为什么不使用Boost.Filesystem之类的东西? Boost.Filesystem two-minute tutorial举例说明了如何使用directory iterators实现搜索。