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
我编写了一个程序来模仿 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