clarify some language; insert spaces in args to confuse beginners less (#400)
* clarify some language; insert spaces in args to confuse beginners less * fix 2>&1 footgun, explain it and how to avoid it * add cadence and AstroSnail to credits
This commit is contained in:
parent
e668250e16
commit
dfe84da074
|
@ -224,24 +224,52 @@ another. Let's say you have a need for both standard out and standard error to
|
||||||
go to the same file. You can do this with a command like this:
|
go to the same file. You can do this with a command like this:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rustc foo.rs 2>&1 > foo.log
|
$ rustc foo.rs > foo.log 2>&1
|
||||||
```
|
```
|
||||||
|
|
||||||
This tells the shell to point standard error to standard out and then the
|
This tells the shell to point standard out to `foo.log`, and then standard
|
||||||
combined output to `foo.log`. There's a short form of this too:
|
error to standard out (which is now `foo.log`). There's a footgun here though;
|
||||||
|
the order of the redirects matters. Consider the following:
|
||||||
|
|
||||||
|
```
|
||||||
|
$ rustc foo.rs 2>&1 > foo.log
|
||||||
|
error: expected one of `!` or `::`, found `main`
|
||||||
|
--> foo.rs:1:5
|
||||||
|
|
|
||||||
|
1 | fun main() {}
|
||||||
|
| ^^^^ expected one of `!` or `::`
|
||||||
|
|
||||||
|
error: aborting due to previous error
|
||||||
|
$ cat foo.log
|
||||||
|
$ # foo.log is empty, why???
|
||||||
|
```
|
||||||
|
|
||||||
|
We wanted to redirect stderr to `foo.log`, but that didn't happen. Why? Well,
|
||||||
|
the shell considers our redirects one at a time from left to right. When the
|
||||||
|
shell sees `2>&1`, it hasn't considered `> foo.log` yet, so standard out (`1`)
|
||||||
|
is still our terminal. It dutifully redirects stderr to the terminal, which is
|
||||||
|
where it was already going anyway. Then it sees `1 > foo.log`, so it redirects
|
||||||
|
standard out to `foo.log`. That's the end of it though. It doesn't
|
||||||
|
retroactively redirect standard error to match the new standard out, so our
|
||||||
|
errors get dumped to our terminal instead of the file.
|
||||||
|
|
||||||
|
Confusing right? Lucky for us, there's a short form that redirects both at the
|
||||||
|
same time, making this mistake impossible:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rustc foo.rs &> foo.log
|
$ rustc foo.rs &> foo.log
|
||||||
```
|
```
|
||||||
|
|
||||||
[Where can I expect to use that?](conversation://Mara/hmm)
|
This will put standard out and standard error to `foo.log` the same way that
|
||||||
|
`> foo.log 2>&1` will.
|
||||||
|
|
||||||
[It's a bourne shell extension, but I've tested it in `zsh` and `fish`. You can
|
[Will that work in every shell?](conversation://Mara/hmm)
|
||||||
also do `&|` to pipe both standard out and standard error at the same time in
|
|
||||||
the same way you'd do `2>&1 | whatever`.](conversation://Cadey/enby)
|
|
||||||
|
|
||||||
That will put standard out and standard error to `foo.log` the same way that
|
[It's a bourne shell (`bash`) extension, but I've tested it in `zsh` and `fish`.
|
||||||
`2>&1 > foo.log` will. You can also use this with `>>`:
|
You can also do `&|` to pipe both standard out and standard error at the same
|
||||||
|
time in the same way you'd do `2>&1 | whatever`.](conversation://Cadey/enby)
|
||||||
|
|
||||||
|
You can also use this with `>>`:
|
||||||
|
|
||||||
```
|
```
|
||||||
$ rustc foo.rs &>> foo.log
|
$ rustc foo.rs &>> foo.log
|
||||||
|
@ -265,9 +293,13 @@ error: aborting due to previous error
|
||||||
|
|
||||||
[How do I redirect standard in to a file?](conversation://Mara/hmm)
|
[How do I redirect standard in to a file?](conversation://Mara/hmm)
|
||||||
|
|
||||||
The answer there is not directly! There is a workaround in the form of a tool
|
Well, you don't. Standard in is an input, so you can change where it comes
|
||||||
called `tee` which outputs its standard in to both standard out and a file. For
|
_from_, not where it goes.
|
||||||
example:
|
|
||||||
|
But, maybe you want to make a copy of a program's input and send it somewhere
|
||||||
|
else. There is a way to do _that_ using a command called `tee`. `tee` copies
|
||||||
|
its standard input to standard output, but it also writes a second copy to a
|
||||||
|
file. For example:
|
||||||
|
|
||||||
```console
|
```console
|
||||||
$ dmesg | tee dmesg.txt | grep 'msedge'
|
$ dmesg | tee dmesg.txt | grep 'msedge'
|
||||||
|
@ -345,6 +377,6 @@ What else could you do with pipes and redirection? The cloud's the limit!
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
Thanks to violet spark for looking over this post and fact-checking as well as
|
Thanks to violet spark, cadence, and AstroSnail for looking over this post and
|
||||||
helping mend some of the brain dump and awkward wording into more polished
|
fact-checking as well as helping mend some of the brain dump and awkward
|
||||||
sentences.
|
wording into more polished sentences.
|
||||||
|
|
Loading…
Reference in New Issue