]> git.proxmox.com Git - rustc.git/blame - src/doc/book/src/ch12-01-accepting-command-line-arguments.md
New upstream version 1.63.0+dfsg1
[rustc.git] / src / doc / book / src / ch12-01-accepting-command-line-arguments.md
CommitLineData
13cf67c4
XL
1## Accepting Command Line Arguments
2
3Let’s create a new project with, as always, `cargo new`. We’ll call our project
4`minigrep` to distinguish it from the `grep` tool that you might already have
5on your system.
6
f035d41b 7```console
13cf67c4
XL
8$ cargo new minigrep
9 Created binary (application) `minigrep` project
10$ cd minigrep
11```
12
13The first task is to make `minigrep` accept its two command line arguments: the
923072b8
FG
14file path and a string to search for. That is, we want to be able to run our
15program with `cargo run`, two hyphens to indicate the following arguments are
16for our program rather than for `cargo`, a string to search for, and a path to
17a file to search in, like so:
13cf67c4 18
f035d41b 19```console
923072b8 20$ cargo run -- searchstring example-filename.txt
13cf67c4
XL
21```
22
23Right now, the program generated by `cargo new` cannot process arguments we
dc9dc135 24give it. Some existing libraries on [crates.io](https://crates.io/) can help
13cf67c4
XL
25with writing a program that accepts command line arguments, but because you’re
26just learning this concept, let’s implement this capability ourselves.
27
28### Reading the Argument Values
29
30To enable `minigrep` to read the values of command line arguments we pass to
04454e1e
FG
31it, we’ll need the `std::env::args` function provided in Rust’s standard
32library. This function returns an iterator of the command line arguments passed
33to `minigrep`. We’ll cover iterators fully in [Chapter 13][ch13]<!-- ignore
34-->. For now, you only need to know two details about iterators: iterators
35produce a series of values, and we can call the `collect` method on an iterator
36to turn it into a collection, such as a vector, that contains all the elements
37the iterator produces.
13cf67c4 38
04454e1e
FG
39The code in Listing 12-1 allows your `minigrep` program to read any command
40line arguments passed to it and then collect the values into a vector.
13cf67c4
XL
41
42<span class="filename">Filename: src/main.rs</span>
43
44```rust
74b04a01 45{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-01/src/main.rs}}
13cf67c4
XL
46```
47
48<span class="caption">Listing 12-1: Collecting the command line arguments into
49a vector and printing them</span>
50
51First, we bring the `std::env` module into scope with a `use` statement so we
52can use its `args` function. Notice that the `std::env::args` function is
48663c56
XL
53nested in two levels of modules. As we discussed in [Chapter
547][ch7-idiomatic-use]<!-- ignore -->, in cases where the desired function is
923072b8
FG
55nested in more than one module, we’ve chosen to bring the parent module into
56scope rather than the function. By doing so, we can easily use other functions
57from `std::env`. It’s also less ambiguous than adding `use std::env::args` and
58then calling the function with just `args`, because `args` might easily be
59mistaken for a function that’s defined in the current module.
13cf67c4
XL
60
61> ### The `args` Function and Invalid Unicode
62>
63> Note that `std::env::args` will panic if any argument contains invalid
64> Unicode. If your program needs to accept arguments containing invalid
65> Unicode, use `std::env::args_os` instead. That function returns an iterator
66> that produces `OsString` values instead of `String` values. We’ve chosen to
67> use `std::env::args` here for simplicity, because `OsString` values differ
68> per platform and are more complex to work with than `String` values.
69
70On the first line of `main`, we call `env::args`, and we immediately use
71`collect` to turn the iterator into a vector containing all the values produced
72by the iterator. We can use the `collect` function to create many kinds of
73collections, so we explicitly annotate the type of `args` to specify that we
74want a vector of strings. Although we very rarely need to annotate types in
75Rust, `collect` is one function you do often need to annotate because Rust
76isn’t able to infer the kind of collection you want.
77
923072b8
FG
78Finally, we print the vector using the debug macro. Let’s try running the code
79first with no arguments and then with two arguments:
13cf67c4 80
f035d41b 81```console
74b04a01
XL
82{{#include ../listings/ch12-an-io-project/listing-12-01/output.txt}}
83```
13cf67c4 84
f035d41b 85```console
74b04a01 86{{#include ../listings/ch12-an-io-project/output-only-01-with-args/output.txt}}
13cf67c4
XL
87```
88
89Notice that the first value in the vector is `"target/debug/minigrep"`, which
90is the name of our binary. This matches the behavior of the arguments list in
91C, letting programs use the name by which they were invoked in their execution.
92It’s often convenient to have access to the program name in case you want to
93print it in messages or change behavior of the program based on what command
94line alias was used to invoke the program. But for the purposes of this
95chapter, we’ll ignore it and save only the two arguments we need.
96
97### Saving the Argument Values in Variables
98
04454e1e
FG
99The program is currently able to access the values specified as command line
100arguments. Now we need to save the values of the two arguments in variables so
101we can use the values throughout the rest of the program. We do that in Listing
10212-2.
13cf67c4
XL
103
104<span class="filename">Filename: src/main.rs</span>
105
6a06907d 106```rust,should_panic,noplayground
74b04a01 107{{#rustdoc_include ../listings/ch12-an-io-project/listing-12-02/src/main.rs}}
13cf67c4
XL
108```
109
110<span class="caption">Listing 12-2: Creating variables to hold the query
923072b8 111argument and file path argument</span>
13cf67c4
XL
112
113As we saw when we printed the vector, the program’s name takes up the first
04454e1e
FG
114value in the vector at `args[0]`, so we’re starting arguments at index `1`. The
115first argument `minigrep` takes is the string we’re searching for, so we put a
13cf67c4 116reference to the first argument in the variable `query`. The second argument
923072b8
FG
117will be the file path, so we put a reference to the second argument in the
118variable `file_path`.
13cf67c4
XL
119
120We temporarily print the values of these variables to prove that the code is
121working as we intend. Let’s run this program again with the arguments `test`
122and `sample.txt`:
123
f035d41b 124```console
74b04a01 125{{#include ../listings/ch12-an-io-project/listing-12-02/output.txt}}
13cf67c4
XL
126```
127
128Great, the program is working! The values of the arguments we need are being
129saved into the right variables. Later we’ll add some error handling to deal
130with certain potential erroneous situations, such as when the user provides no
131arguments; for now, we’ll ignore that situation and work on adding file-reading
132capabilities instead.
48663c56
XL
133
134[ch13]: ch13-00-functional-features.html
135[ch7-idiomatic-use]: ch07-04-bringing-paths-into-scope-with-the-use-keyword.html#creating-idiomatic-use-paths