0

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;

}
Learning from masters
  • 1,388
  • 1
  • 14
  • 28
  • 4
    Try `printf("Reading file [%s]\n", path);`. – melpomene May 19 '17 at 10:53
  • `fopen` does not print anything! – too honest for this site May 19 '17 at 10:56
  • Please xing, write that as an answer so I can select your answer properly. Dammit newlines... – Learning from masters May 19 '17 at 10:58
  • 2
    parsing `ls` output is overhead (process creation, I/O), fragile (`ls` might be missing, or incompatible version) and error-prone (see your problem) -- suggest you use your platform's API for such things, see `opendir()` and `readdir()` –  May 19 '17 at 11:13
  • 2
    Also, No need for `sizeof(path) - 1`. Just use `sizeof(path)`. – Spikatrix May 19 '17 at 11:25
  • 1
    You could -and probably should- avoid your `popen`; see [readdir(3)](http://man7.org/linux/man-pages/man3/readdir.3.html), [stat(2)](http://man7.org/linux/man-pages/man2/stat.2.html), [nftw(3)](http://man7.org/linux/man-pages/man3/nftw.3.html)... and read [Advanced Linux Programming](http://advancedlinuxprogramming.com/) – Basile Starynkevitch May 19 '17 at 12:11

2 Answers2

3

There are 2 bugs in your code:

  1. 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';
    
  2. Use 'ls -A1', since 'ls -F' adds a '*' in binary name:

    fp = popen("ls -A1 |grep -v /", "r");

3

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;

}
Learning from masters
  • 1,388
  • 1
  • 14
  • 28