2

I am running a system call within my main function and I wanted to know if I could read the command line output from the system call line by line within the main function.

I have been looking online for any tips or ideas on how to do this, but I cannot find any. One thing to note is that I do not want the output to be written into a file and then read from that file, but rather read the command line output line by line.

int main(int argc, char const *argv[]) {
    system("ls -al");
    return 0;
}

For example, in the above code, I want to print all the files in the current directory through this C function. With that information, I only want to print the ones that have been updated in April (distinguished with an "Apr" in the 6th column). Is it possible for me to read the output line by line, split the line into an array and check to see if the specified column is "Apr", and if so how? Any and all help/advice would be highly appreciated.

dmoini
  • 313
  • 2
  • 15
  • Now is the question - do you want to do the filtering in you system shell using `system("ls -al | grep Apr | blabla")` or do you want to use `popen("ls -al");` and filter the output by reading the lines from a `FILE*` object returned by `popen` by using some `strstr` or similar? Anyway this is too broad. | On the second thought, I think you just simply search for [`popen`](http://man7.org/linux/man-pages/man3/popen.3.html). – KamilCuk Apr 23 '19 at 17:43
  • I apologize for not specifying more clearly. I would like to filter the output by reading the lines rather than just grep it because I also want to do this for other system command outputs with integer outputs and comparing whether those integer outputs are greater than a given number. – dmoini Apr 23 '19 at 18:01
  • 1
    This sounds like an XY problem. Perhaps you actually want to [list the contents of a directory](https://stackoverflow.com/questions/4204666/how-to-list-files-in-a-directory-in-a-c-program) then [check the modification date of each file](https://stackoverflow.com/questions/10446526/get-last-modified-time-of-file-in-linux). – Nick ODell Apr 23 '19 at 20:22
  • Such tasks are better done using scripting languages like `python` or `shell` instead of `c` – balki Apr 23 '19 at 21:30
  • @balki While definitely much easier in a language like Python, I am required to do it in C. – dmoini Apr 23 '19 at 21:59

1 Answers1

4

You can use popen, like this:

#include <stdio.h>

int main()
{
    FILE * fp = popen("ls -l", "r");
    char buf[1024];
    while (fgets(buf, 1024, fp)) {
        printf("returned: \"%s\"\n", buf);
    }
    return 0;
}

This only shows reading each line from the command, you'll still need to split the text to do what you want.

And just because it is fun, here it is with a simple function to grab fields out of a string buffer:

char * get_field(char *buffer, int field)
{
    int white = 1; // simple state machine
    char *p;
    char *first = NULL;
    for (p=buffer; *p; p++) {
        if (white) {
            if (*p > ' ') {
                white = 0;
                first = p;
            }
        } else {
            if (*p <= ' ') {
                white = 1;
                field--;
                if (!field && first)
                    return strndup(first, p-first);
            }
        }
    }
    return NULL;
}

int main()
{
    FILE * fp = popen("ls -l", "r");
    char buf[1024];

    while (fgets(buf, 1024, fp)) {
        char *month = get_field(buf, 6);
        if (month) {
            printf("  month: \"%s\"\n", month);
            free(month);
        }
        char *file = get_field(buf, 9);
        if (file) {
            printf("  file: \"%s\"\n", file);
            free(file);
        }
    }
    return 0;
}

This is a simple brute force method, suitable for simple programs, and does not provide the functionality of a typical split() function. But it illustrates one way to do this sort of thing in C.

Alcamtar
  • 1,478
  • 13
  • 19