We've now seen both input and output redirection, and some practical uses for both. We have not, however, combined both forms of redirection yet, and this is very much possible!
You will probably not use this too often, though; most commands accept the input as an argument, and often supply a flag that allows you to specify a file to output to. But knowledge is power, and if you ever come across a command that does not have these arguments, you know you can solve this yourself.
Try the following on your command line, and try to understand why you get the results that you see:
reader@ubuntu:~/scripts/chapter_12$ cat stderr.c
#include <stdio.h>
int main()
{
// Print messages to stdout and stderr.
fprintf(stdout, "This is sent to stdout.\n");
fprintf(stderr, "This is sent to stderr.\n");
return 0;
}
reader@ubuntu:~/scripts/chapter_12$ grep 'stderr' < stderr.c
// Print messages to stdout and stderr.
fprintf(stderr, "This is sent to stderr.\n");
reader@ubuntu:~/scripts/chapter_12$ grep 'stderr' < stderr.c > /tmp/grep-file
reader@ubuntu:~/scripts/chapter_12$ cat /tmp/grep-file
// Print messages to stdout and stderr.
fprintf(stderr, "This is sent to stderr.\n");
As you can see, we can use both < and > on the same line to redirect both the input and output. First, we use grep with input redirection in the grep 'stderr' < stderr.c command (which is technically what grep 'stderr' stderr.c does as well). We see the output in our Terminal.
Next, we add > /tmp/grep-file right behind that command, which means we'll redirect our stdout to that /tmp/grep-file file. We no longer see the output in the Terminal, but when we cat the file we get it back, so it was successfully written to the file.
Since we're in the advanced part of this chapter, we will demonstrate that it actually doesn't matter where the input redirection is placed:
reader@ubuntu:~/scripts/chapter_12$ < stderr.c grep 'stdout' > /tmp/grep-file-stdout
reader@ubuntu:~/scripts/chapter_12$ cat /tmp/grep-file-stdout
// Print messages to stdout and stderr.
fprintf(stdout, "This is sent to stdout.\n");
Here, we specified the input redirection at the beginning of our command. For us, this feels like the more logical approach when you consider the flow, but this causes the actual command (grep) to appear roughly halfway through the command, which messes up the readability.
This is mostly a moot point because, in practice, we have found very little use for both input and output redirection; even in this example, we would just write the command as grep 'stdout' stderr.c > /tmp/grep-file-stdout and the confusing construction is gone.
But really understanding what is going on with input and output, and how some commands do some of the heavy lifting for you, is worth your time! These are exactly the kind of issues you're going to encounter in more complex scripts, and fully understanding this will save you a lot of troubleshooting time.