Reading a file name from piped command

廉价感情. 提交于 2019-12-01 12:38:15

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

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.

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

char c = (char)fgetc(stdin)
标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!