Reading a file name from piped command

2019-02-20 15:12发布

So I'm trying to get the C program to read a filename from the command line in the following format: cat (filename path) | (program name)

i can get it to read the name of the input file when its entered as a command line argument, but it won't read from the concatenated argument

here's the code, right now its reading the name of the file as if written after the program name on the command line.

#include <stdio.h>
#include <string.h>

//initialize file pointer
FILE *file;

//initialize global variables
#define DEFAULT_LEN 70

//main
int main(int argv, char *argc[]){

 //open File for reading
 file = fopen (argc[1],"r");
 //test for failure of file open, if failed, print message, quit
 if(file == NULL){
      printf("I'm sorry Dave, I'm araid I can't do that.\n");
  printf("Open the file \"%s\" that is.\n", argc[1]);
  return(0);
 }

 //read the first line of a file into an array
 char temp[DEFAULT_LEN]; //where the read data is put
 fgets(temp,DEFAULT_LEN,file); //stops at DEFAULT_LEN on \n

 //print out temp
 printf("%s\n", temp);

 //close file, return 0 for main
 fclose(file);
 return(0);
}

any help would be appreciated

标签: c pipe filenames
3条回答
地球回转人心会变
2楼-- · 2019-02-20 16:05

The reason your program can't get the file name is because you're not giving it to it.

If you run your program as:

prog hello.txt

it's given the argument hello.txt in argc/argv.

However, what you're doing is:

cat hello.txt | prog

which means the shell is opening the file and feeding it into the standard input of your program. Actually, to be more accurate, cat is opening the file and the shell is simply connecting the standard output of cat to the standard input of prog.

One way around this is to check the number of arguments (argc is usually the count, argv[] the values, despite the roundabout way you have it in your code) and, if it's zero, argc == 1, read your file from standard input.

Only if an argument is given do you open that file and read it. That's the way a lot of UNIX utilities work:

od -xcb hello.txt        # will dump the file.
cat hello.txt | od -xcb  # will dump the file, but using standard input.
echo hello | od -xcb     # will dump your "hello" string.

Some even change their behaviour depending on how they're invoked, wc being one example - it shows the file name(s) if it knows them:

pax> wc -l qq.c
     29 qq.c
pax> cat qq.c | wc -l
     29
pax> wc -l *.c
      0 a b.c
    168 binmath.c
     49 qq-save.c
     29 qq.c
     11 qq2.c
      5 qqq.c
     18 xx.c
    280 total
pax> cat *.c | wc -l
    280

Note that last case - because all files are being presented over the single standard input stream, there's no way to tell how many files there are. wc will just tally up the entire contents of that stream.

Try this instead:

#include <stdio.h>
#include <string.h>

#define DEFAULT_LEN 70

int main (int argc, char *argv[]) {
    FILE *file;

    // Either select standard input or open the given file.

    if (argc == 1) {
        file = stdin;
    } else {
        file = fopen (argv[1], "r");
        if (file == NULL) {
            printf ("I'm sorry Dave, I can't do that\n");
            printf (" (open the file '%s', that is).\n", argv[1]);
            return 1;
        }
    }

    // Now you're connected to stdin or the file itself, no
    //  difference in handling them (unless you do weird fseek
    //  sort of stuff).

    char temp[DEFAULT_LEN];
    fgets (temp, DEFAULT_LEN, file);

    printf ("%s\n", temp);

    // Only close file if you opened it yourself.

    if (argc != 1)
        fclose (file);
    return 0;
}

This allows you to use both the file and standard input method as follows:

pax> prog prog.c
#include <stdio.h>

pax> echo hello | prog
hello
查看更多
叛逆
3楼-- · 2019-02-20 16:09

To read from the contantenated, you need to read from STDIN

char c = (char)fgetc(stdin)
查看更多
爷的心禁止访问
4楼-- · 2019-02-20 16:14

Piping content into a process does not put the values into argv; rather, it puts the values onto that process's stdin.

You need to check if argc is greater than 1. If it is, then argv[1] has the filename you've been given (well, the first argument to the program, anyway). If not, you need to read from stdin to get the filename.

查看更多
登录 后发表回答