## Write to `stderr` Instead of `stdout`

Right now, we're writing all of our output to the terminal with `println!`. This works, but most terminals provide two kinds of output: "standard out" is used for most information, but "standard error" is used for error messages. This makes it easier to do things like "Print error messages to my terminal, but write other output to a file."

We can see that our program is only capable of printing to `stdout` by redirecting it to a file using `>` on the command line, and running our program without any arguments, which causes an error:

    $ cargo run > output.txt

The `>` syntax tells the shell to write the contents of standard out to output.txt instead of the screen. However, if we open output.txt after running we'll see our error message:

    Problem parsing arguments: not enough arguments

We'd like this to be printed to the screen instead, and only have the output from a successful run end up in the file if we run our program this way. Let's change how error messages are printed as shown in Listing 12-17:

Filename: src/main.rs

    extern crate greprs;

    use std::env;
    use std::process;
    use std::io::prelude::*;

    use greprs::Config;

    fn main() {
        let mut stderr = std::io::stderr();
        let args: Vec<String> = env::args().collect();

        let config = Config::new(&args).unwrap_or_else(|err| {
            writeln!(
                &mut stderr,
                "Problem parsing arguments: {}",
                err
            ).expect("Could not write to stderr");

            process::exit(1);
        });

        if let Err(e) = greprs::run(config) {

            writeln!(
                &mut stderr,
                "Application error: {}",
                e
            ).expect("Could not write to stderr");

            process::exit(1);
        }
    }

Listing 12-17: Writing error messages to `stderr` instead of `stdout`

Rust does not have a convenient function like `println!` for writing to standard error. Instead, we use the `writeln!` macro, which is sort of like `println!`, but it takes an extra argument. The first thing we pass to it is what to write to. We can acquire a handle to standard error through the `std::io::stderr` function. We give a mutable reference to `stderr` to `writeln!`; we need it to be mutable so we can write to it! The second and third arguments to `writeln!` are like the first and second arguments to `println!`: a format string and any variables we're interpolating.

Let's try running the program again in the same way, without any arguments and redirecting `stdout` with `>`:

    $ cargo run > output.txt
    Problem parsing arguments: not enough arguments

Now we see our error on the screen, but `output.txt` contains nothing. If we try it again with arguments that work:

    $ cargo run to poem.txt > output.txt

We'll see no output to our terminal, but `output.txt` will contain our results:

Filename: output.txt

    Are you nobody, too?
    How dreary to be somebody!

## Summary

In this chapter, we've covered how to do common I/O operations in a Rust context. By using command line arguments, files, environment variables, and the ability to write to `stderr`, you're now prepared to write command line applications. By using the concepts from previous chapters, your code will be well-organized, be able to store data effectively in the appropriate data structures, handle errors nicely, and be well tested. We also saw a real-world scenario where lifetime annotations are needed to ensure references are always valid.

Next, let's explore how to make use of some features of Rust that were influenced by functional languages: closures and iterators.