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