c ++似乎无法过滤掉我的递归目录列表程序中的点文件

c++ can't seem to filter out the dot files in my recursive directory listing program

我编写了一个程序来模仿 linux 的 ls 及其选项:

-a: include dot files
-d: show only this directory
-l: show long form
-h: prints utilities

到目前为止,所有选项似乎都可以正常工作,但是,默认情况下,在执行类似以下操作时:./a.out -d(显示当前目录中的所有文件)我已将其设置为默认情况下,点文件不应显示(这是在函数 getdir 中设置的)。它们应该只在输入 -a 标志时显示,例如 ./a.out -ad 。但是,这些点文件似乎总是存在。关于我做错了什么的任何想法? (我考虑过最小化代码但决定反对它,因为很多功能交织在一起,并且通过测试其他一些选项更容易查看是否一切)。

Sample output:
[John@storm ~]$ ./a.out -d
.ccache
.local
.mozilla
private
public_html
.Xauthority
.bash_history
.bash_logout
.bash_profile
.bashrc
.emacs
.procmailrc
.procmailrc.orig
.config
.esd_auth
OSGradedLabs
linux.txt
OS
omp1.cpp
omp
test.cpp
test2.cpp
test3.cpp
.viminfo
a.out

While it should be:
a.out  linux.txt  omp  omp1.cpp  OS  OSGradedLabs  private  public_html  test2.cpp  test3.cpp  test.cpp



#include<iostream>
#include<string.h>
#include<fstream>
#include<dirent.h>
#include <unistd.h>
#include <getopt.h>
#include <string>
#include <vector>
#include <algorithm>
#include <sys/types.h>
#include <sys/stat.h>
#include <pwd.h>
#include <grp.h>
#include <cstring>

using namespace std;

class dirls 
{
    public:
        dirls();
        dirls(bool a, bool d, bool f, bool l, bool h);
        void print_usage(string s);
        void longlisting(string dir, vector<string>& files);
        void getdir(string dir, vector<string>& files, bool recursive);
        void initiate(string s, vector<string>& files, vector<string>& paths);
        bool ishflag() { return fflag; };
      

    private:
        bool aflag;
        bool dflag;
        bool fflag;
        bool lflag;
        bool hflag;
        
};
dirls::dirls()
{
    //this->pathQueue = pathQueue;
    aflag = false;
    dflag = false;
    fflag = false;
    lflag = false;
    hflag = false;
}

dirls::dirls(bool a, bool d, bool f, bool l, bool h) 
{
    aflag = a;
    dflag = d;
    fflag = f;
    lflag = l;
    hflag = h;
}

void dirls::print_usage(string s)
{
    cout << "Usage: ";
    cout << s;
    cout << " [(-[adflh]+) (dir)]*" << endl;
    cout << "-a: include dot files" << endl;
    cout << "-f: follow symbolic links" << endl;
    cout << "-d: only this directory" << endl;
    cout << "-l: long form" << endl;
    cout << "-h: prints this message" << endl;
}


bool isDir(string dir) // check if an argument is a directory
{
    struct stat fileInfo;
    stat(dir.c_str(), &fileInfo);
    if (S_ISDIR(fileInfo.st_mode)) 
        return true;
    else 
        return false;
    
}

void dirls::getdir(string dir, vector<string>& files, bool recursive) 
{
    DIR* dp; //create the directory object
    struct dirent* entry; //create the entry structure
    dp = opendir(dir.c_str()); //open directory by converting the string to const char*
    if (dir.at(dir.length() - 1) != '/') {
        dir = dir + "/";
    }
    if (dp != NULL) { //if the directory isn't empty
        while (entry = readdir(dp)) { //while there is something in the directory
            
            if (aflag == false && dflag == false) // if -a is not included then exclude dot files
            {
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
                { //and if the entry isn't "." or ".."
                    //if (isDir(dir + entry->d_name) == true && recursive == true) {//check if the new path is a directory, and if it is (and recursion is specified as true), recurse.
                    if (isDir(dir + entry->d_name) == true && isDir(dir))
                    {
                        files.push_back(string(entry->d_name)); //add entry to the list of files
                        getdir(dir + entry->d_name, files, true); //recurse
                    }
                    else
                    {
                        files.push_back(string(entry->d_name));//add the entry to the list of files
                    }
                }
            }
            else if (aflag == true && dflag == false)//if -a included and -d is not included then incude dot files and recurse
            {
                if (isDir(dir + entry->d_name) == true && isDir(dir))
                {
                    files.push_back(string(entry->d_name)); //add entry to the list of files
                    getdir(dir + entry->d_name, files, true); //recurse
                }
                else
                {
                    files.push_back(string(entry->d_name));//add the entry to the list of files
                }

            }
            else if (aflag == false && dflag == true) // if -a is not included and -d is included then don't incude dot files and remove recursion
            {
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
                { //and if the entry isn't "." or ".."
                    //if (isDir(dir + entry->d_name) == true && recursive == true) {//check if the new path is a directory, and if it is (and recursion is specified as true), recurse.
                    if (isDir(dir + entry->d_name) == true && isDir(dir))
                    {
                        files.push_back(string(entry->d_name)); //add entry to the list of files
                        //getdir(dir + entry->d_name, files, true); //recurse
                    }
                    else
                    {
                        files.push_back(string(entry->d_name));//add the entry to the list of files
                    }
                }
            }
            else if (aflag == true && dflag == true) // if -a is included and -d is included then inclue dot files and remov recursion
            {
                if (isDir(dir + entry->d_name) == true && isDir(dir))
                {
                    files.push_back(string(entry->d_name)); //add entry to the list of files
                    //getdir(dir + entry->d_name, files, true); //recurse
                }
                else
                {
                    files.push_back(string(entry->d_name));//add the entry to the list of files
                }
            }
            else
            { };
            
        }
        (void)closedir(dp); //close directory
    }
    else 
    {
        perror("Couldn't open the directory.");
    }
}

void dirls::longlisting(string dir, vector<string>& files)
{
    string complete;
    for (int i = 0; i < files.size(); i++)
    {
        struct stat buf;
        lstat(files[i].c_str(), &buf);

        uid_t userId = buf.st_uid;
        gid_t groupId = buf.st_gid;

        struct passwd* user = getpwuid(userId);
        struct group* group = getgrgid(groupId);

        string perms = string((S_ISDIR(buf.st_mode)) ? "d" : "-") + ((buf.st_mode & S_IRUSR) ? "r" : "-") + ((buf.st_mode & S_IWUSR) ? "w" : "-") + ((buf.st_mode & S_IXUSR) ? "x" : "-") + ((buf.st_mode & S_IRGRP) ? "r" : "-") + ((buf.st_mode & S_IWGRP) ? "w" : "-") + ((buf.st_mode & S_IXGRP) ? "x" : "-") + ((buf.st_mode & S_IROTH) ? "r" : "-") + ((buf.st_mode & S_IWOTH) ? "w" : "-") + ((buf.st_mode & S_IXOTH) ? "x" : "-");

        complete = perms + " " + to_string(buf.st_size) + " " + user->pw_name + " " + group->gr_name + " " + dir;
        files[i] = complete + files[i];
    }
}

void dirls::initiate(string s, vector<string>& files, vector<string>& paths)
{
    

    while (!paths.empty()) 
    {
       
        char* pathname = (char*)paths.front().c_str();

        getdir(paths.front(), files, true);
        
        if (paths.size() > 1) 
        {
            cout << pathname << ":" << endl;
        }

        if (hflag) 
        {
            print_usage(s);
            paths.erase(paths.begin());
            continue;
        }

        if (lflag) 
        {
            longlisting(paths.front(), files);
            paths.erase(paths.begin());
            continue;
        }

        if (aflag) 
        {
            paths.erase(paths.begin());
            continue;
        }

        if (dflag) 
        {
            paths.erase(paths.begin());
            continue;
        }

       
        paths.erase(paths.begin());
        
    }
}



int main(int argc, char* argv[]) 
{
    int opt = 0;
    string first = argv[0];
    string dir = argv[1];
    struct stat buf;
    bool a = false, d = false, f = false, l = false, h = false;

    vector<string> files = vector<string>(); // holds the files in a directory
    vector<string> paths = vector<string>(); // holds the paths

    while ((opt = getopt(argc, argv, "adflh")) != -1)
    {
        switch (opt)
        {
            case 'a':
                a = true;
                break;
            case 'd':
                d = true;
                break;
            case 'f':
                f = true;
                break;
            case 'l':
                l = true;
                break;
            case 'h':
                h = true;
                break;
            default:
                break;
        }
       
    }
    
    dirls x = dirls(a, d, f, l, h);
  
    
    for (int i = optind; i < argc; i++)
    {
        paths.push_back(argv[i]);
    }
    
    if (paths.empty()) 
    {
        paths.push_back(".");
    }

    x.initiate(first, files, paths);
 
    
    for (int i = 0; i < files.size(); i++)
    {
        if ((h == true) && (a == false) && (d == false) && (f == false) && (l == false))
            break;
        cout << files[i] << endl;
        
    }
   
    return 0; 
    
}

我很确定问题出在 getdir 上,也许是因为我对 strcmp 的理解,所以我会在下面放一个该函数的副本以便于查看。

void dirls::getdir(string dir, vector<string>& files, bool recursive) 
{
    DIR* dp; //create the directory object
    struct dirent* entry; //create the entry structure
    dp = opendir(dir.c_str()); //open directory by converting the string to const char*
    if (dir.at(dir.length() - 1) != '/') {
        dir = dir + "/";
    }
    if (dp != NULL) { //if the directory isn't empty
        while (entry = readdir(dp)) { //while there is something in the directory
            
            if (aflag == false && dflag == false) // if -a is not included then exclude dot files | NOT WORKING
            {
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
                { //and if the entry isn't "." or ".."
                    //if (isDir(dir + entry->d_name) == true && recursive == true) {//check if the new path is a directory, and if it is (and recursion is specified as true), recurse.
                    if (isDir(dir + entry->d_name) == true && isDir(dir))
                    {
                        files.push_back(string(entry->d_name)); //add entry to the list of files
                        getdir(dir + entry->d_name, files, true); //recurse
                    }
                    else
                    {
                        files.push_back(string(entry->d_name));//add the entry to the list of files
                    }
                }
            }
            else if (aflag == true && dflag == false)//if -a included and -d is not included then incude dot files and recurse
            {
                if (isDir(dir + entry->d_name) == true && isDir(dir))
                {
                    files.push_back(string(entry->d_name)); //add entry to the list of files
                    getdir(dir + entry->d_name, files, true); //recurse
                }
                else
                {
                    files.push_back(string(entry->d_name));//add the entry to the list of files
                }

            }
            else if (aflag == false && dflag == true) // if -a is not included and -d is included then don't incude dot files and remove recursion
            {
                if (strcmp(entry->d_name, ".") != 0 && strcmp(entry->d_name, "..") != 0)
                { //and if the entry isn't "." or ".."
                    //if (isDir(dir + entry->d_name) == true && recursive == true) {//check if the new path is a directory, and if it is (and recursion is specified as true), recurse.
                    if (isDir(dir + entry->d_name) == true && isDir(dir))
                    {
                        files.push_back(string(entry->d_name)); //add entry to the list of files
                        //getdir(dir + entry->d_name, files, true); //recurse
                    }
                    else
                    {
                        files.push_back(string(entry->d_name));//add the entry to the list of files
                    }
                }
            }
            else if (aflag == true && dflag == true) // if -a is included and -d is included then inclue dot files and remov recursion
            {
                if (isDir(dir + entry->d_name) == true && isDir(dir))
                {
                    files.push_back(string(entry->d_name)); //add entry to the list of files
                    //getdir(dir + entry->d_name, files, true); //recurse
                }
                else
                {
                    files.push_back(string(entry->d_name));//add the entry to the list of files
                }
            }
            else
            { };
            
        }
        (void)closedir(dp); //close directory
    }
    else 
    {
        perror("Couldn't open the directory.");
    }
}


strcmp 比较整个字符串,因此您的函数过滤掉与“.”的完全匹配项。和 ”..”。如果你只想检查文件名的第一个字母,你可以在字符串中使用数组索引

entry->d_name[0] != '.'

或者只比较一定数量字符的第一个字符的 strncmp 函数

strncmp(entry->d_name, ".", 1) != 0

http://www.cplusplus.com/reference/cstring/strncmp/