Need To Eliminate Directories From File Listing in C - 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.

Related

Count the number of files in, and below a directory in Linux C recursively

I write a function to count the number of files in, and below a directory (including files in the sub directory).
However, When I test the code on a directory with sub directory, it always report error said: "fail to open dir: No such file or directory".
Is there any thing I could do to make it work?
int countfiles(char *root, bool a_flag)//a_flag decide if it including hidden file
{
DIR *dir;
struct dirent * ptr;
int total = 0;
char path[MAXPATHLEN];
dir = opendir(root); //open root dirctory
if(dir == NULL)
{
perror("fail to open dir");
exit(1);
}
errno = 0;
while((ptr = readdir(dir)) != NULL)
{
//read every entry in dir
//skip ".." and "."
if(strcmp(ptr->d_name,".") == 0 || strcmp(ptr->d_name,"..") == 0)
{
continue;
}
//If it is a directory, recurse
if(ptr->d_type == DT_DIR)
{
sprintf(path,"%s%s/",root,ptr->d_name);
//printf("%s/n",path);
total += countfiles(path, a_flag);
}
if(ptr->d_type == DT_REG)
{
if(a_flag == 1){
total++;
}
else if (a_flag == 0){
if (isHidden(ptr->d_name) == 0){
total++;
}
}
}
}
if(errno != 0)
{
printf("fail to read dir");
exit(1);
}
closedir(dir);
return total;
}
Is there anything I could make it to work?
Sure, lots. Personally, I'd start by using the correct interface for this stuff, which in Linux and POSIXy systems would be nftw(). This would lead to a program that was not only shorter and more effective, but would not as easily get confused if someone renames a directory or file in the tree being scanned at the same time.
Programmers almost never implement opendir()/readdir()/closedir() as robustly and as efficiently as nftw(), scandir(), glob(), or the fts family of functions do. Why teachers still insist on using the archaic *dir() functions in this day and age, puzzles me to no end.
If you have to use the *dir functions because your teacher does not know POSIX and wants you to use interfaces you should not use in real life, then look at how you construct the path to the new directory: the sprintf() line. Perhaps even print it (path) out, and you'll probably find the fix on your own.
Even then, sprintf() is not something that is allowed in real life programs (because it will cause a silent buffer overrun when the arguments are longer than expected; and that CAN happen in Linux, because there actually isn't a fixed limit on the length of a path). You should use at minimum snprintf() and check its return value for overruns, or in Linux, asprintf() which allocates the resulting string dynamically.

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).

How to properly use S_ISREG function

EDIT: After some help from the forum it was made clear that this issue was not in the use of S_ISREG() but in my use of lstat(). Sorry for the misleading question.
I'm looking in a directory and trying to tell the difference between regular files and sub-directories.
I've looked through other people's issues with this problem, and while some were similar, none were answered clearly enough to fix my code.
int find(char *argv)
{
DIR *pointerToDir;
struct dirent *pointerToDirent;
struct stat status;
int mode;
pointerToDir = opendir(argv);
if(pointerToDir == NULL)
{
printf("Can't open that directory (or it doesn't exist)\n");
closedir(pointerToDir);
return 0;
}
else
{
while((pointerToDirent = readdir(pointerToDir)) != NULL)
{
lstat(pointerToDirent->d_name, &status);
mode = S_ISREG(status.st_mode);
if(mode != 0)
printf("%s must be a file\n", pointerToDirent->d_name);
else
printf("%s must be a dir\n", pointerToDirent->d_name);
}
closedir(pointerToDir);
return 0;
}
}
I pass the program a test directory that has 2 sub-directories and 2 regular files. The layout would be something like this:
dir1
sub1
sub2
dir1.txt
test.c
Now when I run my program and pass "dir1" as the argument, I would expect it to return the following:
. must be a dir
.. must be a dir
sub1 must be a dir
dir1.txt must be a file
sub2 must be a dir
test.c must be a file
But instead, it returns that they are all "dirs". What am I missing?

How to access directory files in C?

I'm trying to add all the files in the current directory to my implemented archive. What function(s) could I use to access all these files? After doing some research online and in the man pages, all I have found is simple I/O like read, write, close, etc.
You can try with this.
main() {
DIR *d;
struct dirent *e;
e=malloc(sizeof(struct dirent));
d=opendir("<your_directory_name>");
while ((e = readdir(d)) != NULL) {
printf("%d %s\n", e->d_type, e->d_name);
}
closedir(d);
}
In Unix, readdir ; in Windows, see here for FindFirstFile(). Then go file by file in a loop and do what you want.
This web page seems to have what you want.
http://www.gnu.org/software/libc/manual/html_mono/libc.html#Opening-a-Directory

listing the files in a directory and delete them in C/C++

In a "C" code I would like to list all the files in a directory and delete the oldest one. How do I do that?
Can I use popen for that or we have any other solutions??
Thanks,
From the tag, I assume that you want to do this in a POSIX compliant system. In this case a code snippet for listing files in a folder would look like this:
#include <dirent.h>
#include <sys/types.h>
#include <stdio.h>
DIR* dp;
struct dirent* ep;
char* path = "/home/mydir";
dp = opendir(path);
if (dp != NULL)
{
printf("Dir content:\n");
while(ep = readdir(dp))
{
printf("%s\n", ep->d_name);
}
}
closedir(dp);
To check file creation or modification time, use stat (man 2 stat). For removing file, just use function remove(const char* path)
On Linux (and indeed, any POSIX system), you read a directory by calling opendir() / readdir() / closedir(). You can then call stat() on each directory entry to determine if it's a file, and what its access / modification / status-change times are.
If your definition of "oldest" depends on the creation time of the file, then you're on shaky ground - traditionally UNIX didn't record the creation time. On Linux, some recent filesystems do provide it through the extended attribute file.crtime (which you access using getxattr() from sys/xattr.h), but you'll have to handle the common case where that attribute doesn't exist.
You can scan the directory using readdir and opendir
or, if you want to traverse (recursively) a file hierarchy fts or nftw. Don't forget to ignore the entries for the current directory "." and the parent ".." one. You probably want to use the stat syscall too.

Resources