What libraries for file search

What libraries would i need to write a file searching program for linux? Thanks.
Probably the standard C++ library is sufficient.

What's wrong with find(1)?
Last edited on
If you've got a recent version of GCC, you should be able to use std::filesystem. If not, try boost::filesystem. They both have methods to walk the file system. If you're masochistic, you could use ftw() include <ftw.h>.
For a Linux specific solution check out this linuxQuestions answer;
https://www.linuxquestions.org/questions/programming-9/c-list-files-in-directory-379323/

For an explanation and some resources on the dir struct and dirent.h;
https://stackoverflow.com/questions/12991334/members-of-dirent-structure


Depends on what you mean by file searching. Are you looking for files by name, or by content?
by name
I have got:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>

using namespace std;

/*function... might want it in some class?*/
int getdir (string dir, vector<string> &files)
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir.c_str())) == NULL) {
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    }

    while ((dirp = readdir(dp)) != NULL) {
        files.push_back(string(dirp->d_name));
    }
    closedir(dp);
    return 0;
}

int main()
{
	string dir; // = string("/.");
    cout <<"Which directory would you like to list? (. for current directory)\n";
    cin >> dir;
    vector<string> files = vector<string>();

    getdir(dir,files);

    for (unsigned int i = 0;i < files.size();i++) {
        cout << files[i] << endl;
    }
    return 0;
}


I notice that:

dirp->d_name

calls up the filename, is their anyway I could do some logic with "dirp->d_name" and maybe strcmp to look for files of a certain name? thanks.
Last edited on
... Yes, like the list of files output from blender like this;
myout_01.png
myout_02.png
myout_03.png
myout_04.png

Instead of strcmp in this situation, since you've already got a vector of strings with those file names, I would prefer to use the find() function from the string class.

1
2
3
4
5
6
if(files[i].find("myout_", 0) != std::string::npos )
{
// parse the number out of the file if you need that info
// do some processing on the file
//etc
}


Also the string's substr function might be useful for finding all files of a certain extension
1
2
3
4
5
string fName = files[i];
if(fName.substr(fName.length() - 4) == ".ext")
{
    // found a file that ends in ".ext", now do something with it...
}


Out of curiosity, have you looked into elb's suggestion about std::filesystem? I hadn't read much into c++17 and was not aware of all that it offers when I suggested dirent.h, and it offers it in a cross-system manner which means only learning one library and being able to build the same code on almost any system... Nothing wrong with dirent.h, but there may be many benefits to the other option...
Last edited on
Ok that's fantastic. I have my first file searching program, that's fab. Can you guys suggest any api's and libraries I should be learning to build a gui for it?

Thanks.
ok I Have another question.

So far I have:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88

#include <sys/types.h>
#include <dirent.h>
#include <errno.h>
#include <vector>
#include <string>
#include <iostream>
#include <bits/stdc++.h>

using namespace std;
 
/*function... might want it in some class?*/
int getdir (string dir, vector<string> &files)
{
    DIR *dp;
    struct dirent *dirp;
    if((dp  = opendir(dir.c_str())) == NULL){
        cout << "Error(" << errno << ") opening " << dir << endl;
        return errno;
    } else {
		cout <<"The directory " << dir << " has been found.\n";
	}

    while ((dirp = readdir(dp)) != NULL){
        files.push_back(string(dirp->d_name));
    }
    
    closedir(dp);
    return 0;
}

bool mycomp(string a, string b){
return a<b;
}

vector<string> alphabeticallySort(vector<string> a){
	int n = a.size();
	sort(a.begin(),a.end(),mycomp);
	return a;
}

int main()
{
	string dir;
    cout <<"Which directory would you like to list? (. for current directory)\n";
    cin >> dir;
    
    vector<string> files = vector<string>();

    getdir(dir,files);
    
    /*for (unsigned int i = 0;i < files.size();i++){
        cout << files[i] << endl;
    }
    
    cout <<"\n";
    
    files=alphabeticallySort(files);

	for (unsigned int i = 0;i < files.size();i++){
    cout << files[i] << endl;
    }
	*/
	cout<<"\n";

string theFile;

cout<< "What file would you like to look for?\n\n";
cin>>theFile;

		for (unsigned int i = 0;i < files.size();i++){
		if(files[i].find(theFile, 0) != std::string::npos )
        cout << files[i] << endl;
		}
		
		cout <<"\n";
			
    return 0;

}

/*
 * string fName = files[i];
if(fName.substr(fName.length() - 4) == ".ext")
{
    // found a file that ends in ".ext", now do something with it...
}
*/


Is there any way I can make find only return file names not dirs and also make it search recursively through subdirectories?
https://stackoverflow.com/questions/4553012/checking-if-a-file-is-a-directory-or-just-a-file

There are several methods in the link above. It looks to me that the easiest is just to open the path as a folder using openddir(filePath), and if it returns NULL then it either is a file, the path is incorrect, or you do not have permissions to read that folder.

If you need more specific info on what the path is, then you could use the stat.h method.


Last edited on
ok,considering the above options and doing further research,

I have the following code at the moment

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
#include <sys/types.h>
#include <vector>
#include <string>
#include <cstring>
#include <iostream>
#include <bits/stdc++.h>
#include <dirent.h>
#include <errno.h>

using namespace std;

int getdir (string dir, vector<string> &files)
{
	DIR *dp;
	struct dirent *dirp;
	if((dp = opendir(dir.c_str())) == NULL){
		cout <<"Error(" << errno << ") opening " << dir << endl;
		return errno;
	} else {
		cout<<"The directory " << dir << " has been found.\n";
	}
	while ((dirp = readdir(dp)) !=NULL){
		files.push_back(string(dirp->d_name));
	}
	
	closedir(dp);
	return 0;
}

int isFile(const char* name)
{
	DIR* directory = opendir(name);
	
	if(directory !=NULL)
	{
		closedir(directory);
		return 0;
	}
	
	if(errno == ENOTDIR)
	{
		return 1;
	}
	
	return -1;
}

int main()
{
	string dir;
	cout <<"Which directory would you like to list? (. for current directory)\n";
	cin >> dir;
	
	vector<string> files = vector<string>();
	
	getdir(dir, files);
	
	for (unsigned int i = 0; i < files.size(); i++){
		cout << files[i] << endl;
	}
	
	cout <<"\n";
	
	string theFile;
	
	cout <<"What file would you like to look for?\n\n";
	cin>>theFile;
	
	for (unsigned int i = 0; i < files.size();i++){
		if(files[i].find(theFile, 0) != std::string::npos )
		cout << files[i] << endl;
	}
	
	cout <<"\n";
	
	char file[theFile.size() +1];
	strcpy (file, theFile.c_str());
	
	char directory[dir.size() +1];
	strcpy (directory, dir.c_str());
	
	printf("Is %s a file? %s.\n", file,
	((isFile(file) == 1) ? "Yes" : "No"));
	printf("Is %s a directory? %s.\n", directory,
	((isFile(directory) == 0) ? "Yes" : "No"));
	
	return 0;
}


is there any way I can use the logic on lines 83-85 in conjunction with the vector files to output only filenames from a directory? thanks.
you mean not show folders at all?
rewire the logic there to: if it is a file, print the name, else do not print the name (no else statement, its an empty / implied do nothing else).
Topic archived. No new replies allowed.