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

发布于 2024-11-03 20:31:52 字数 2058 浏览 1 评论 0原文

嘿大家。我需要编写一个 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; 

}

Hey everyone. I need to write a POSIX program to search through an entire file system for a specified file starting at the top directory. I've got some code which isn't done at all, but when I run it, and check to see if a particular file is a directory, it's saying this file which is not at all a directory is a directory and is trying to move into it, causing an error. I'm not sure how I can tell it that this type of file isn't a directory.

Here's my code. I know it's not perfect and I could probably do some things differently in the way of getting the directory names and passing them into the function. Either way, I'm pretty sure I have to do this recursively.

The file in question is /dev/dri/card0 and I'm running this from a Debian virtual machine.

#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; 

}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

暖心男生 2024-11-10 20:31:52

POSIX.2 需要一个有效的“find”命令。

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

POSIX.2 requires a working "find" command.

#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);
}
听,心雨的声音 2024-11-10 20:31:52

->d_name 仅返回文件名,而不返回文件路径。您需要统计(尚未构造)new_Directory 而不是dptr->d_name

如果一个目录包含多个子目录,也会遇到问题。对于第一个子目录之后的每个子目录,您的 new_Directory 构造都是不正确的。

您从未关闭您的目录句柄,因此您耗尽了资源。您还应该考虑在递归之前将整个目录加载到数组中,以避免耗尽句柄。

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

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

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

更新:添加代码。

->d_name returns just the name of the file, not the path to the file. You need to stat (not yet constructed) new_Directory instead of dptr->d_name.

You also have a problem if a directory contains more than one subdirectories. Your construction of new_Directory is incorrect for each subdirectory after the first.

You never closedir your directory handle, so you run out of resources. You should also consider loading the entire directory into an array before recursing to avoid running out of handles.

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

Update: Added second problem.

Update: Added third problem.

Update: Added code.

丘比特射中我 2024-11-10 20:31:52

不是为了OP的利益,他写道“重点是想出一种自己做的方法”,而是为了子孙后代的利益,这是一种使用 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();
  }
}

Not for the benefit of the OP, who writes "The point is to come up with a way to do it myself," but rather for the benefit of posterity, here is a way to use 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();
  }
}
踏雪无痕 2024-11-10 20:31:52

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

Use fork, execv and the Unix implemented /usr/bin/find process and redirect its output for your result area?

捎一片雪花 2024-11-10 20:31:52

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

I'm not sure if it's POSIX or not but the nftw library function is widely available on UNIX (HP-UX, AIX, Linux).

小…楫夜泊 2024-11-10 20:31:52

你的问题是“在树中搜索匹配项”

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

如果你遵循符号链接,你会遇到麻烦;所以测试一下它们,不要跟随它们。

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

Your problem is "search a tree for a match"

BFS and DFS are the canonical basic algorithms. Give them a start node and go.

You will get into trouble if you follow symlinks; so test for them and don't follow them.

You should be able to map each point in the *FS algorithms to a directory operation.

一曲琵琶半遮面シ 2024-11-10 20:31:52

既然 C++ 是一种选择,为什么不使用 Boost 之类的东西。文件系统Boost.Filesystem 两分钟教程 给出了如何使用 目录迭代器

Since C++ is an option, why not use something like Boost.Filesystem? The Boost.Filesystem two-minute tutorial gives an example of how to implement your search using directory iterators.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文