2011-04-27 70 views
2

嘿大家。我需要編寫一個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; 

} 
+4

btw,'find/-name card0' – ikegami 2011-04-27 19:32:07

+2

此外,[nftw](http://pubs.opengroup.org/onlinepubs/9699919799/functions/nftw.html),雖然這是XSI而不是POSIX基礎。 – Random832 2011-04-27 19:39:20

+0

@ikegami - 我不認爲他在尋找card0。我認爲他意味着/ dev/dri/card0的S_ISDIR爲true,但是opendir(「/ dev/dri/card0」)失敗。 – 2011-04-27 21:08:00

回答

2

->d_name只返回文件的名稱,而不是文件的路徑。您需要stat(尚未構建)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

或者您可以使用'fstatat'來避免組裝字符串(以及相關的競爭條件在目錄結構中)。 – 2011-04-27 19:46:27

1

使用fork,execv和Unix實現了/ usr/bin/find過程並將其輸出重定向到你的結果區?

+0

我不能。關鍵是想出一個辦法來自己做:P謝謝你。 – Cuthbert 2011-04-27 19:43:27

+0

POSIX兼容的程序也可以在Windows上運行... – 2011-04-27 19:45:46

+0

@ d2jxp:好的,對不起。 – Naszta 2011-04-27 19:45:52

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

我不確定它是不是POSIX,但nftw庫函數在UNIX(HP-UX,AIX,Linux)上廣泛可用。

+0

優秀的建議。 – wnoise 2011-05-10 05:09:09

1

你的問題是「搜索樹匹配」

BFS和DFS是規範的基本算法。給他們一個開始節點並去。

如果您遵循符號鏈接,您將遇到麻煩;所以測試他們,不要跟着他們。

您應該能夠將* FS算法中的每個點映射到目錄操作。

2

不爲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(); 
    } 
} 
相關問題