Reading file names from a directory - c++

I'm reading all file names from a certain directory using this function:
void getdir(std::string dir, std::list<std::string>& files)
{
DIR *dp;
struct dirent *dirp;
if((dp = opendir(dir.c_str())) == NULL)
{
std::cout<< "Error: path " << dir << " onbekend!\n";
}
else
{
while ((dirp = readdir(dp)) != NULL)
{
files.push_back(std::string(dirp->d_name));
}
closedir(dp);
}
}
When I print them out, I get '.' or '..' too with the filenames. But the file '.' or '..' is not in the directory.
I'm using ubuntu 12.04 :)

. is current directory, and .. is parent directory, you will find them in every directory.

Related

How to load all files and directory to memory in c++

I'm doing a program to management of directories and their contents and I want to run a program in determinate directory and load this directory and all the files contained to memory. And return true in case of bee successful.
Example I have a folder that contain 3 files(center.txt, main.csv, re.txt) and 2 folders(1, 2) inside folder 1 is the file(file.txt). I want load this to memory, the files and the directory( and the files that determinate directory contains).
I want to do I pre-run the directory and while find a file load them to memory.
I have this code to list the files. I want now load to memory
void Load(const string &path) {
DIR *pDIR;
ifstream inn;
string str;
string c = path;
const char *f = c.c_str();
struct dirent *entry;
if (pDIR = opendir(f)) {
while (entry = readdir(pDIR)) {
cout << entry->d_name << "\n";
}
closedir(pDIR);
}
}
Piece of code to loop through recursively and load file contents as strings into map. Hope this helps:
#include <dirent.h>
#include <fstream>
#include <iostream>
#include <map>
std::map<std::string, std::string> Load(const std::string& path) {
// Map with file name and contents
std::map<std::string, std::string> files;
DIR* pDIR;
const char* f = path.c_str();
pDIR = opendir(f);
if (!pDIR) {
return files;
}
struct dirent* entry;
while ((entry = readdir(pDIR))) {
std::string fileName = std::string(entry->d_name);
// Skip current dir and parent dir
if (fileName == "." || fileName == "..") {
continue;
}
// Add current path to the filename
fileName = path + "/" + fileName;
// This is directory, load recursively
if (entry->d_type == DT_DIR) {
std::cout << "Found directory: " << fileName << std::endl;
auto ret = Load(fileName);
// Merge files
files.insert(ret.begin(), ret.end());
continue;
}
std::cout << "Found file: " << fileName << std::endl;
// Read file contents and add it to map
std::ifstream file(fileName);
std::string content((std::istreambuf_iterator<char>(file)), std::istreambuf_iterator<char>());
files[fileName] = content;
}
closedir(pDIR);
return files;
}
int main(int argc, char** argv) {
auto files = Load(".");
return 0;
}

C++ folder opening and file counting

So this is my code but I cant prevent it from printing out: . .. and it counts them as a file. I couldnt understand why.
The output is:
.
1files.
..
2files.
course3.txt
3files.
course2.txt
4files.
course1.txt
5files.
But there are only 3 files... It should say 3 files instead it counts that . .. and i dont know its meaning.
int folderO(){
DIR *dir;
struct dirent *ent;
int nFiles=0;
if ((dir = opendir ("sampleFolder")) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
std::cout << ent->d_name << std::endl;
nFiles++;
std::cout << nFiles << "files." << std::endl;
}
closedir (dir);
}
else {
/* could not open directory */
perror ("");
return EXIT_FAILURE;
}
}
. and .. are meta directories, current directory and parent directory respectively.
What you have found is that subdirectories are being printed along with files. And so are symlinks and other "weird" Unix-y stuff. Couple ways to filter those out if you don't want them printed:
If your system supports d_type in the dirent structure, check that d_type == DT_FILE before printing. (GNU page on dirent listing possible d_types)
if (ent->d_type == DT_FILE)
{
std::cout << ent->d_name << std::endl;
nFiles++;
std::cout << nFiles << "files." << std::endl;
}
if d_type is not supported, stat the file name and check that it is a file st_mode == S_ISREG.
struct stat statresult;
if (stat(ent->d_name, &statresult) == 0)
{
if (statresult.st_mode == S_ISREG)
{
std::cout << ent->d_name << std::endl;
nFiles++;
std::cout << nFiles << "files." << std::endl;
}
}
And of course there is the dumb-simple strcmp-based if statement, but this will list all other subdirectories.
Crap. Sorry. C++. that last line should be "And of course there is the dumb-simple std::string operator==-based if statement, but this will list all other subdirectories."
. is current directory inode (technically, a hardlink), .. is parent directory.
These are there for navigation. They're directories, perhaps you can ignore them if they are directories?
A Google search would have revealed that these are special folder names with these meanings:
. the current directory
.. the parent directory
Any tutorial on iterating a directory shows you how to filter these out with a simple "if" statement.

How to read specific file names of a directory into an array

I tried to read all file names of a directory into array and my code successfully addes whole file names into array. However, what i need it to do,
1st one is getting ,not all of them, only spesific file names which end like .cpp or .java. It should be done in this part and my comparisons did not work. How can i do that ?
DIR *dir;
struct dirent *dirEntry;
vector<string> dirlist;
while ((dirEntry = readdir(dir)) != NULL)
{
//here
dirlist.push_back(dirEntry->d_name);
}
2dn one is getting the directory location from user. I couldn't do that also, it only works if i write the location adress, how can i get location from user to get files ?
dir = opendir(//here);
I think this would work for your case,
DIR* dirFile = opendir( path );
if ( dirFile )
{
struct dirent* hFile;
errno = 0;
while (( hFile = readdir( dirFile )) != NULL )
{
if ( !strcmp( hFile->d_name, "." )) continue;
if ( !strcmp( hFile->d_name, ".." )) continue;
// in linux hidden files all start with '.'
if ( gIgnoreHidden && ( hFile->d_name[0] == '.' )) continue;
// dirFile.name is the name of the file. Do whatever string comparison
// you want here. Something like:
if ( strstr( hFile->d_name, ".txt" ))
printf( "found an .txt file: %s", hFile->d_name );
}
closedir( dirFile );
}
Ref: How to get list of files with a specific extension in a given folder
#include <iostream>
#include "boost/filesystem.hpp"
using namespace std;
using namespace boost::filesystem;
int main(int argc, char *argv[])
{
path p (argv[1]);
directory_iterator end_itr;
std::vector<std::string> fileNames;
std::vector<std::string> dirNames;
for (directory_iterator itr(p); itr != end_itr; ++itr)
{
if (is_regular_file(itr->path()))
{
string file = itr->path().string();
cout << "file = " << file << endl;
fileNames.push_back(file);
}
else if (is_directory(itr->path()))
{
string dir = itr->path().string();
cout << "directory = " << dir << endl;
dirNames.push_back(dir);
}
}
}

Error opening existing directory using opendir in c++

I am making use of opendir() as below to access a directory.
DIR *dp;
if((dp = opendir(dir.c_str())) == NULL) {
cout << "Error(" << errno << ") opening " << dir << endl;
return errno;
}
However, I keep getting the error below, even though the directory exists.
Error(2) opening /path/to/folder/
I am able to get a list of file names when I do ls /path/to/folder
Be aware that /path/to/folder is different from /path/to/folder/
errno value 2 means ENOENT (it's an abbreviaton for Error NO ENTry) that is "Directory does not exist, or name is an empty string".
How do you define dir in your code?
std::string dir = "/path/to/folder/";
DIR* dp = opendir(dir.c_str());
if (dp == NULL)
{
std::cout << "Error(" << errno << ") opening " << dir << std::endl;
perror("opendir");
return errno;
}
closedir(dp);
Update #1:
Try to call you shell script:
main.sh folder/ foldername
Where main.sh contains:
#!/bin/sh
path="$1$2"
echo "$path"
ls -l "$path"

Find all files in a directory and its subdirectory

I would like to list all files in a given directory and its different subdirectory.
I found some code that I modified but it doing a never ending loop and I don't understand why.
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));
string test=dir+"/"+dirp->d_name;
getdir(test,files);
}
closedir(dp);
return 0;
}
My main:
int main()
{
string dir = string(".");
vector<string> files = vector<string>();
getdir(dir,files);
for (unsigned int i = 0;i < files.size();i++) {
cout << files[i] << endl;
}
return 0;
}
How could I fix it?
This is likely due to the "." directory entry returned as the first entry which represents the current directory.
This causes your algorithm to try to list the entries for ./. and then ././. endlessly repeating until your program would eventual crash when it ran out of memory.
There's also a ".." directory entry which represents the parent directory and can cause a similar recursive problem.
As noted by Jerry Coffin, symbolic links can also cause a very similar issue if you have links which point to a directory which is the parent or ancestor of the symbolic link. This could be avoided with a much more complicated check or just simply excluding DT_LNK type entries all together.
Another issue is that you're trying to call getdir on files as well as subdirectories.
Try the following changes
while ((dirp = readdir(dp)) != NULL) {
string name(dir->d_name);
if (name != "." && name != "..") {
string test=dir+"/"+name;
files.push_back(test);
if (dir->d_type == DT_DIR) {
getdir(test,files);
}
}
}