What libraries for file search

Feb 10, 2020 at 10:43pm
What libraries would i need to write a file searching program for linux? Thanks.
Feb 10, 2020 at 10:56pm
Probably the standard C++ library is sufficient.

What's wrong with find(1)?
Last edited on Feb 10, 2020 at 10:57pm
Feb 11, 2020 at 1:25am
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>.
Feb 16, 2020 at 12:08am
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


Feb 16, 2020 at 3:13pm
Depends on what you mean by file searching. Are you looking for files by name, or by content?
Feb 21, 2020 at 5:19pm
by name
Feb 21, 2020 at 5:23pm
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 Feb 21, 2020 at 5:26pm
Feb 22, 2020 at 8:56am
... 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 Feb 22, 2020 at 9:22am
Feb 22, 2020 at 3:46pm
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.
Feb 22, 2020 at 3:54pm
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?
Feb 22, 2020 at 6:23pm
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 Feb 22, 2020 at 6:24pm
Feb 26, 2020 at 4:52pm
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.
Mar 5, 2020 at 2:18pm
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.