Get only the files included in a directory in c / Ubuntu - c

I have to create a listing of the files contained inside a specific directory, I have done the code below(part of a bigger programm), but I would like my programm to ignore any possible folders that could be included inside the directory.
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
int main ()
{
DIR *dirptr;
struct dirent *entry;
dirptr = opendir ("synchedFolder");
if (dirptr != NULL)
{
while (entry = readdir (dirptr))
{
if(strcmp(entry->d_name,"..")!=0 && strcmp(entry->d_name,".")!=0)
puts (entry->d_name);
}
(void) closedir (dirptr);
}
else
perror ("ERROR opening directory");
}

If you want to list only files, but no directories, you have to add the following check:
entry->d_type == DT_REG
or
entry->d_type != DT_DIR

There's stat() and lstat() and the return value for stat. In the latter, look out for the S_ISDIR macro.

Short answer is the dirent structure includes the necessary information:
if ( entry->d_type == DT_REG)

Check stat (or lstat)
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
/* int main (void){ */
int main (int argc, char **argv){
int i,result=0;
struct stat buf;
/* print_S_I_types(); */
for (i=1; i < argc; i++){
if (lstat(argv[i], &buf) < 0) {
fprintf(stderr, "something went wrong with %s, but will continue\n",
argv[i]);
continue;
} else {
if S_ISREG(buf.st_mode){
printf("argv[%d] is normal file\n",i);
}else {
printf("argv[%d] is not normal file\n",i);
}
}
}
return 0;
}

Working code for listing files (without directories):
#include <stdio.h>
#include <dirent.h>
#include <stdlib.h>
int main()
{
DIR *dir;
struct dirent *ent;
if ((dir = opendir ("/home/images")) != NULL)
{
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL)
{
if(ent->d_type!= DT_DIR)
{
printf ("%s\n", ent->d_name);
}
}
closedir (dir);
}
else
{
/* could not open directory */
perror ("");
return EXIT_FAILURE;
}
}

Related

Trying to create code in C that print all directories starting from a root directory passed

EXAMPLE
Imagine I have a directory called Alpha and I want it as root.
Alpha contains: some files and other two directories Beta and Gamma,
Beta contains: some files and another directory called Theta,
Gamma contains: some files,
Theta contains: some files.
INPUT/OUTPUT
Using input as: ./myfind Alpha
I'll want as output:
Alpha
Beta
Gamma
Theta
(I don't care about the order).
MY CODE
I tried with this code but it doesn't work. I'll want to do a recursive function to do it and i can't use POSIX.
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <sys/stat.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <stdlib.h>
#include <errno.h>
#if !defined(NAME_MAX)
#define NAME_MAX 256
#endif
int find(const char *passed_dir_name) {
if (chdir(passed_dir_name) == -1) {
perror("FATAL ERROR CHANGING DIRECTORY");
return -1;
}
DIR *current_directory;
if ((current_directory = opendir(".")) == NULL) {
perror("FATAL ERROR OPENING CURRENT WORKING DIRECTORY");
return -1;
}
struct dirent *dir;
while ((dir = readdir(current_directory)) != NULL) {
struct stat statbuf;
stat(dir->d_name, &statbuf);
if (S_ISDIR(statbuf.st_mode)) {
fprintf(stdout, "%s\n", dir->d_name);
find(dir->d_name);
}
}
if (closedir(current_directory) == -1) {
perror("FATAL ERROR CLOSING CURRENT WORKING DIRECTORY");
exit(EXIT_FAILURE);
}
}
int main(int argc, char **argv) {
if (argc != 2) {
fprintf(stderr, "ERROR: Run as ./myfind directory\n");
exit(EXIT_FAILURE);
}
const char *dir = argv[1];
struct stat statbuf;
stat(dir, &statbuf);
if (!S_ISDIR(statbuf.st_mode)) {
fprintf(stderr, "FATAL ERROR: %s IS NOT A DIRECTORY\n", dir);
exit(EXIT_FAILURE);
}
find(dir);
exit(EXIT_SUCCESS);
}
The problem is you change the current directory when you recurse into a subdirectory but you do not change back to the parent directory when returning from the recursive function.
You could add a chdir(".."); at the end of the find function, but it might not work in all cases:
if a directory has more than 2 hard links
if you traverse symbolic links
It is preferable to compute the path of the destination directory for the recursive call to find() by concatenating the passed_dir_name, a / and dir->d_name and avoid changing the current directory.
Here is a modified version of find() for the simplistic approach:
int find(const char *passed_dir_name) {
if (chdir(passed_dir_name) == -1) {
perror("FATAL ERROR CHANGING DIRECTORY");
return -1;
}
DIR *current_directory;
if ((current_directory = opendir(".")) == NULL) {
perror("FATAL ERROR OPENING CURRENT WORKING DIRECTORY");
chdir("..");
return -1;
}
struct dirent *dir;
while ((dir = readdir(current_directory)) != NULL) {
struct stat statbuf;
stat(dir->d_name, &statbuf);
if (S_ISDIR(statbuf.st_mode)) {
fprintf(stdout, "%s\n", dir->d_name);
find(dir->d_name);
}
}
if (closedir(current_directory) == -1) {
perror("FATAL ERROR CLOSING CURRENT WORKING DIRECTORY");
exit(EXIT_FAILURE);
}
chdir("..");
}

fopen: file does not exist but it does

I want to read all files that I can find in the folder where my executable is, except the runnable file that I'm running. I code the following code but, although this list correctly the files that I have in my folder, I cannot open them with fopen because fopen prints that the file doesn't exists. If I do gedit "path of the file obtained from my program in c" then it opens perfectly from the term. Where is the bug?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
#include <unistd.h>
int main (int argc, char **argv) {
//Determining the number of files we have.
//We call to a bash command http://stackoverflow.com/questions/646241/c-run-a-system-command-and-get-output
FILE *fp, *fin;
char path[1035], cwd[1024];
int scanned = 0;
/* Open the command for reading. */
//https://askubuntu.com/questions/370697/how-to-count-number-of-files-in-a-directory-but-not-recursively
//This count soft and hard links also (I think)
fp = popen("ls -F |grep -v /", "r");
if (fp == NULL) {
printf("Failed to run command\n" );
exit(1);
}
/* Read the output a line at a time - output it. */
//Loop for each file. Be careful! if the exe is inside, it will also be counted!
while (fgets(path, sizeof(path)-1, fp) != NULL) {
printf("Reading file: %s\n", path);
fin=fopen(path,"r");
scanned = 0;
printf("caa");
if (fin != NULL){
printf("AA\n");
fclose(fin);
}
if (!fin)perror("fopen");
printf("Done! \n");
}
/* close */
pclose(fp);
printf("end");
return 0;
}
There are 2 bugs in your code:
when the code updates the "path" variable in your code. It has a newline at the end which needs to be corrected to NUL. This gives an incorrect path.
Something like below can be appended to your code:
while (fgets(path, sizeof(path)-1, fp) != NULL) {
len=strlen(path);
path[len-1]='\0';
Use 'ls -A1', since 'ls -F' adds a '*' in binary name:
fp = popen("ls -A1 |grep -v /", "r");
ok so just in case someone else needs a better approach, I redid the code with the comments I had. Here I let you the new code.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <dirent.h>
#include <sys/types.h>
#include <sys/stat.h>
int isDirectory(const char *path) {
struct stat statbuf;
if (stat(path, &statbuf) != 0)
return 0;
return S_ISDIR(statbuf.st_mode);
}
int main (int argc, char **argv) {
FILE *fp, *fin;
char path[1035], cwd[1024];
int scanned = 0;
int ints;
DIR *dir;
struct dirent *ent;
//getcwd prints directory where the app ran.
if ((dir = opendir (getcwd(cwd, sizeof(cwd)))) != NULL) {
/* print all the files and directories within directory */
while ((ent = readdir (dir)) != NULL) {
/*Skips . and ..*/
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) continue;
if (isDirectory(ent->d_name) != 0) continue;
printf ("Reading file: %s\n", ent->d_name);
scanned = 0;
fin=fopen(ent->d_name,"r");
if (fin != NULL){
while ((scanned = fscanf(fin, "%d", ints)) != EOF) {
if(scanned == 1){
printf("%d\n", ints);
}else {
printf("Whoops! Input format is incorrect!\n");
break;
}
} //LOOP: reading file
fclose(fin);
}
if (!fin)perror("fopen");
printf("Done! \n");
}//LOOP: while opendir
closedir (dir);
} else {
/* could not open directory */
perror ("opendir");
return EXIT_FAILURE;
}
return 0;
}

Recursive listing of directories and files C

My C code for recursively listing directories and files get executed multiple times. I am not sure how to fix it and why it keeps happening... It is not infinite its just like 10 times shows the current directory.
void printdir(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
int spaces = depth;
dp = opendir(dir);
while((entry = readdir(dp))) {
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)) {
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 ||
strcmp("..",entry->d_name) == 0)
continue;
printf("%*s%s/\n",spaces,"",entry->d_name);
/* Recurse at a new indent level */
printdir(entry->d_name,depth+1);
}
else printf("%*s%s\n",spaces,"",entry->d_name);
}
closedir(dp);
}
int print_file(char *file, char *dir, struct stat buf, int showinode, int showlong, int showRec)
{
if (showinode)
printf("%lld ", buf.st_ino);
if (showlong)
print_long(file, dir, buf);
if (showRec)
printdir(dir, 0);
else
printf("%s\n", file);
return 0;
}
Here's a recursive function that lists the directories it comes across, using openat(), fdopendir(), fstatat() to avoid string-operations on paths (and, possibly, race-conditions on the directory-tree):
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <fcntl.h>
int sanerecursivedirsearch(int dirfd)
{
DIR *curdir = fdopendir(dirfd);
if (!curdir)
{
perror("fdopendir()");
close(dirfd);
return -1;
}
struct dirent *direp;
while (!!(direp = readdir(curdir)))
{
if (!strcmp(direp->d_name, "..") || !strcmp(direp->d_name, "."))
continue;
struct stat statbuf;
fstatat(dirfd, direp->d_name, &statbuf, 0);
if (S_ISDIR(statbuf.st_mode))
{
int newfd = openat(dirfd, direp->d_name,
O_RDONLY | O_DIRECTORY);
if (newfd == -1)
{
perror("openat()");
continue;
}
printf("directory found:\t%s\n", direp->d_name);
sanerecursivedirsearch(newfd);
}
}
closedir(curdir);
return 0;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
fprintf(stderr, "insufficient command-line arguments");
exit(EXIT_FAILURE);
}
int fd = openat(AT_FDCWD, argv[1],
O_RDONLY | O_DIRECTORY);
if (fd == -1)
{
perror("openat()");
exit(EXIT_FAILURE);
}
sanerecursivedirsearch(fd);
return 0;
}

C Directory and Subdirectory Recursion

I tried to recursively get all files and folder list.But I can only get subdirectories of documents and inside of them.I can't get the other folders which in inside of subdirectory.
I don't know how to do it recursively.I hope you help me
#include <stdio.h>
#include <sys/types.h>
#include <dirent.h>
#include <windows.h>
#include <unistd.h>
#include <string.h>
void list(char *a);
void reader(char *path);
int
main (void)
{
DIR *dp;
struct dirent *ep;
dp = opendir ("C:\\Users\\pen\\Documents\\");
if (dp != NULL)
{
while (ep = readdir (dp)){
GetFileAttributes(ep->d_name);
if(FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(ep->d_name))
{
if (strcmp(".",ep->d_name)==0)
continue;
if (strcmp("..",ep->d_name)==0)
continue;
reader(ep->d_name);
}
}
closedir(dp);
}
else
perror ("Couldn't open the directory");
closedir(dp);
system("pause");
return 0;
}
void reader(char *path){
DIR *da;
struct dirent *ef;
da = opendir(path);
while (ef=readdir(da)){
printf ("%s\n",ef->d_name);
if(FILE_ATTRIBUTE_DIRECTORY & GetFileAttributes(ef->d_name))
{
if (strcmp(".",ef->d_name)==0)
continue;
if (strcmp("..",ef->d_name)==0)
continue;
reader(ef->d_name);
}
}
closedir(da);
}
1) In reader you need to call closedir(da); after the while loop.
2) every call to reader needs to have the absolute path you need to concatenate path
to ef->d_name and then call reader.
3) also to enable debugging you should call perror after a failed readdir call.

scan a directory to find files in c

I'm trying to create a function in c which scans all my path C: \ temp (Windows) to search for a file that I pass (eg test.txt) and each time it finds one return the path to steps another function to write something in the bottom of this file.
I managed to do the function that writes to the file but can not figure out how to do that scans the folder and pass the address of the file found.
#include <unistd.h>
#include <stdio.h>
#include <dirent.h>
#include <string.h>
#include <sys/stat.h>
#include <stdlib.h>
void printdir(char *dir, int depth)
{
DIR *dp;
struct dirent *entry;
struct stat statbuf;
if((dp = opendir(dir)) == NULL) {
fprintf(stderr,"cannot open directory: %s\n", dir);
return;
}
chdir(dir);
while((entry = readdir(dp)) != NULL) {
lstat(entry->d_name,&statbuf);
if(S_ISDIR(statbuf.st_mode)) {
/* Found a directory, but ignore . and .. */
if(strcmp(".",entry->d_name) == 0 ||
strcmp("..",entry->d_name) == 0)
continue;
printf("%*s%s/\n",depth,"",entry->d_name);
/* Recurse at a new indent level */
printdir(entry->d_name,depth+4);
}
else printf("%*s%s\n",depth,"",entry->d_name);
}
chdir("..");
closedir(dp);
}
int main()
{
printf("Directory scan of /home:\n");
printdir("/home",0);
printf("done.\n");
exit(0);
}
Use FindFirstFile function. Here's a good example of this function using.

Resources