The println!
macro is only capable of printing to standard output, so we have to use something else to print to standard error.
First, let’s observe how the content printed by minigrep
is currently being written to standard output, including any error messages we want to write to standard error instead. We’ll do that by redirecting the standard output stream to a file while intentionally causing an error. We won’t redirect the standard error stream, so any content sent to standard error will continue to display on the screen.
Command line programs are expected to send error messages to the standard error stream so we can still see error messages on the screen even if we redirect the standard output stream to a file. Our program is not currently well-behaved: we’re about to see that it saves the error message output to a file instead!
To demonstrate this behavior, we’ll run the program with >
and the file path, output.txt, that we want to redirect the standard output stream to. We won’t pass any arguments, which should cause an error:
The syntax tells the shell to write the contents of standard output to output.txt instead of the screen. We didn’t see the error message we were expecting printed to the screen, so that means it must have ended up in the file. This is what output.txt contains:
Problem parsing arguments: not enough arguments
Printing Errors to Standard Error
We’ll use the code in Listing 12-24 to change how error messages are printed. Because of the refactoring we did earlier in this chapter, all the code that prints error messages is in one function, main
. The standard library provides the eprintln!
macro that prints to the standard error stream, so let’s change the two places we were calling println!
to print errors to use eprintln!
instead.
Filename: src/main.rs
Listing 12-24: Writing error messages to standard error instead of standard output using
Let’s now run the program again in the same way, without any arguments and redirecting standard output with >
:
$ cargo run > output.txt
Now we see the error onscreen and output.txt contains nothing, which is the behavior we expect of command line programs.
We won’t see any output to the terminal, and output.txt will contain our results:
Filename: output.txt
Are you nobody, too?
How dreary to be somebody!
This demonstrates that we’re now using standard output for successful output and standard error for error output as appropriate.
Summary
This chapter recapped some of the major concepts you’ve learned so far and covered how to perform common I/O operations in Rust. By using command line arguments, files, environment variables, and the macro for printing errors, you’re now prepared to write command line applications. Combined with the concepts in previous chapters, your code will be well organized, store data effectively in the appropriate data structures, handle errors nicely, and be well tested.
Next, we’ll explore some Rust features that were influenced by functional languages: closures and iterators.