How to display all files with dirent and stat structs in C - c

OK, so I'm trying to display all files within a given path-name.
For the first path I enter, all files display correctly.
However, when I use a sub-directory path as an argument to the function, it only
displays a single executable (there are other files in the sub-directory as a test).
I absolutely cannot figure out why this is happening.
I will post the relevant snippets of code below, any help with this would be greatly
appreciated.
struct dirent *directory;
DIR *pdirectory;
struct stat fileinfo;
pdirectory=opendir(path);
if (pdirectory==NULL)
{
printf("Error: Unable to open directory\n");
exit(0);
}
printf("%s\n",path);
while ((directory=readdir(pdirectory)) != NULL)
{
if (!stat(directory->d_name,&fileinfo))
{
if (S_ISREG(fileinfo.st_mode))
{
printf("File Name: %s\n",directory->d_name);
printf("File Size: %d bytes\n",fileinfo.st_size);
printf("Last Access: %s\n",ctime(&fileinfo.st_atime));
}
}
}
closedir(pdirectory);
}

Your problem is that the stat(2) system call is failing because your not providing him with the complete path to the files located in the opened directory, in the case you are using your program to open a directory other than the current one.
This explains why your code worked only when opening the current directory.
One solution would be to append the path to the directory you're opening to the name of the file contained in the d_name member of the dirent structure such as :
/path/to/my/directory/name_of_the_file
or
path/to/my/directory/name_of_the_file

Related

How to get the details of the files in the current working directory in C?

I'm trying to display the files of my current working directory in C, however, I also need to include the details of these files such as the date created and their file sizes.
Is there a function that does this in C?
So far here is my code:
int main(
DIR *d;
struct dirent *dir;
d = opendir(".");
if (d) {
while ((dir = readdir(d)) != NULL) {
printf("%s\n", dir->d_name);
}
closedir(d);
}
}
File information is handled not by dirent functions, but by stat().
Note stat() requires a pathname; combining the directory path with the file name from the dirent structure (using strncat) will give you the necessary argument. In this particular case, since file information is only needed for files in the current working directory, the path can be left off and the file name can be used directly as the argument (stat() will then look for the file in the current directory).
The stat struct has the various entries you're interested in, such as st_size for file size and st_ctime for change time (note the latter is a UNIX time, which you'll likely want to convert to a readable string).

Counting number of files and folders in directory

How can I count the number of files and folders in a directory using C. I have no clue. I couldn't write single line code.
I do not care about current directory . and the parent directory..
I have to give a pathname for example “C:/Users/me/Documents/Example” while I'm running the program.
And I need a output like " There are 2 folders and 4 files in this directory".
for linux os
The code below shall list all files and sub-directories in dir_path (for current directory use dir_path = ".").
DESCRIPTION
This description qouted from man7.org link
struct dirent *readdir(DIR *dirp);
readdir()
The readdir() function returns a pointer to a dirent structure
representing the next directory entry in the directory stream pointed
to by dirp. It returns NULL on reaching the end of the directory
stream or if an error occurred. for further details go to the link above for man7.org.
#include <stdio.h>
#include <dirent.h>
int main(void)
{
/* de is Pointer for directory entry */
struct dirent *de;
const char* dir_path = "C:/Users/me/Documents/Example";
/*opendir() returns a pointer of DIR type.*/
DIR *dr = opendir(dir_path);
if (dr == NULL) /* opendir returns NULL if couldn't open directory */
{
printf("Could not open current directory" );
return 0;
}
while ((de = readdir(dr)) != NULL){
printf("%s\n", de->d_name);
}
closedir(dr);
return 0;
}
for windows os
for windows use the header file: fileapi.h see microsoft docs here: fileapi.h
this question answered before in SO in the link below using the FindFirstFile, FindNextFile and FindClose functions.
please review the answer in the link: list directory in windows in C programming language

How to find a specific file in a folder?

So i tried something and everything works fine if the file i'm searching doesn't have an extension in its name (i have a txt file named "instructions" and a fifo file named "myfifo" and they were found).
struct dirent *de=NULL;
DIR *dirr=NULL;
dirr=opendir(".");
while((de=readdir(dirr)) != NULL)
{
printf("%s\n",de->d_name);
if (strcmp(de->d_name,file)==0) printf("Found!\n");
// else printf("kkbesa\n");
}
the variable "file" is declared as char file[100] and i read it from the keyboard.
As i mentioned above, for the files "myfifo" and "instructions" it printed "Found", but when i go for something like "code.c" or "code.exe" it doesn't print anything(Yes, they exist in the current folder).

rename() only works for directory that program is running in?

I am trying to rename a bunch of files in a user specified directory, but it only seems to be working when the user specifies the directory that the program is running from. For example, when running from the command line:
./a.out . "NewName.txt" will work, while
./a.out .. "NewName.txt" will not work. Is there a reason for this? It's on Linux, by the way.
int main(int argc, char** argv){
char* dirpath = argv[1];
char* newName = argv[2];
DIR *d;
struct dirent *dir;
d = opendir(dirpath);
if (d){
while ((dir = readdir(d)) != NULL){
char* filename = dir->d_name;
if (rename(filename,newName) == 0){
printf("Renaming %s -> %s\n",filename,newName);
} else {
printf("Could not rename %s\n",filename);
}
}
}
closedir(d);
}
I have also tried (while running the program from outside of Desktop):
if (rename("~/Desktop/test.txt","~/Desktop/test2.txt") == 0){
printf("Renaming %s -> %s\n",filename,newName);
} else {
printf("Could not rename %s\n",filename);
}
and it still fails.
While readdir() is reading file names from the other directory, your program's current directory is still in a different location. Unless you prefix the source file name with the path to the directory (and the destination file name too) you're trying to rename non-existent files in the current directory, in general.
In pseudo-code:
dir = opendir(remote_directory)
foreach name from dir
rename "remote_directory/name" to "remote_directory/othername"
end for
Note that the pseudo-code works if 'remote_directory' happens to be ., the current directory; you don't need to special-case that code.
I believe that your main problem is that the result from readdir is just the filename. It doesn't include the directory. You need to paste the directory name and the filename from dir->d_name together in your program.
From the documentation:
The old argument points to the pathname of the file to be renamed.
The new argument points to the new pathname of the file.
If the new argument does not resolve to an existing directory entry for a
file of type directory and the new argument contains at least one non-<slash>
character and ends with one or more trailing <slash> characters after all symbolic
links have been processed, rename() shall fail
Looks like you're not referring to an existing element when you use any path other than '.', which is likely why it's failing.
Check the specific errno value to see why.

Need To Eliminate Directories From File Listing in C

I have a problem, in that I need to get a list of the files in a Directory. Using this previous StackOverflow question as a base, I've currently got this code:
void get_files(int maxfiles) {
int count = 0;
DIR *dir;
struct dirent *ent;
dir = opendir(DIRECTORY);
if (dir != NULL) {
/* get all the files and directories within directory */
while ((ent = readdir(dir)) != NULL) {
if (count++ > maxfiles) break;
printf("%s\n", ent->d_name);
}
closedir(dir);
} else {
/* could not open directory */
printf("ERROR: Could not open directory");
exit(EXIT_FAILURE);
}
}
Now it works almost exactly how I want it too, but the problem is that its also listing directories in with he files, and I only want file entries. Is there a easy modification I can make to do this?
You can filter directories using code similar to
this one
POSIX defines fstat which can be used for the purpose of checking whether a file is a directory. It also has a macro to simplify the check.
http://linux.die.net/man/2/fstat
Note that for Windows you may have to use windows API here.
If your struct dirent contains the nonstandard-but-widely-available d_type member, you can use this to filter out directories. Worth having an option to use it and only falling back to stat on systems that don't, since using d_type rather than stat will possibly make your directory listing tens or hundreds of times faster.

Resources