The code and data behind xeiaso.net
5
fork

Configure Feed

Select the types of activity you want to include in your feed.

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

authored by

artemis and committed by
GitHub
dfe84da0 e668250e

+50 -18
+50 -18
blog/fun-with-redirection-2021-09-22.markdown
··· 60 60 feed the `cut` command's standard input using the `<` operator: 61 61 62 62 ```console 63 - $ cut -d' ' -f2 < uname.txt 63 + $ cut -d ' ' -f 2 < uname.txt 64 64 shachi 65 65 chrysalis 66 66 kos-mos ··· 100 100 write it like this: 101 101 102 102 ```sh 103 - cat uname.txt | cut -d' ' -f2 103 + cat uname.txt | cut -d ' ' -f 2 104 104 ``` 105 105 106 106 [The mnemonic we use for remembering the `cut` command is that fields are ··· 110 110 This will get you the exact same output: 111 111 112 112 ```console 113 - $ cat uname.txt | cut -d' ' -f2 113 + $ cat uname.txt | cut -d ' ' -f 2 114 114 shachi 115 115 chrysalis 116 116 kos-mos ··· 123 123 example, if you wanted to sort them you could pipe the result to `sort`: 124 124 125 125 ```console 126 - $ cat uname.txt | cut -d' ' -f2 | sort 126 + $ cat uname.txt | cut -d ' ' -f 2 | sort 127 127 chrysalis 128 128 kos-mos 129 129 ontos ··· 224 224 go to the same file. You can do this with a command like this: 225 225 226 226 ``` 227 + $ rustc foo.rs > foo.log 2>&1 228 + ``` 229 + 230 + This tells the shell to point standard out to `foo.log`, and then standard 231 + error to standard out (which is now `foo.log`). There's a footgun here though; 232 + the order of the redirects matters. Consider the following: 233 + 234 + ``` 227 235 $ rustc foo.rs 2>&1 > foo.log 236 + error: expected one of `!` or `::`, found `main` 237 + --> foo.rs:1:5 238 + | 239 + 1 | fun main() {} 240 + | ^^^^ expected one of `!` or `::` 241 + 242 + error: aborting due to previous error 243 + $ cat foo.log 244 + $ # foo.log is empty, why??? 228 245 ``` 229 246 230 - This tells the shell to point standard error to standard out and then the 231 - combined output to `foo.log`. There's a short form of this too: 247 + We wanted to redirect stderr to `foo.log`, but that didn't happen. Why? Well, 248 + the shell considers our redirects one at a time from left to right. When the 249 + shell sees `2>&1`, it hasn't considered `> foo.log` yet, so standard out (`1`) 250 + is still our terminal. It dutifully redirects stderr to the terminal, which is 251 + where it was already going anyway. Then it sees `1 > foo.log`, so it redirects 252 + standard out to `foo.log`. That's the end of it though. It doesn't 253 + retroactively redirect standard error to match the new standard out, so our 254 + errors get dumped to our terminal instead of the file. 255 + 256 + Confusing right? Lucky for us, there's a short form that redirects both at the 257 + same time, making this mistake impossible: 232 258 233 259 ``` 234 260 $ rustc foo.rs &> foo.log 235 261 ``` 236 262 237 - [Where can I expect to use that?](conversation://Mara/hmm) 263 + This will put standard out and standard error to `foo.log` the same way that 264 + `> foo.log 2>&1` will. 238 265 239 - [It's a bourne shell extension, but I've tested it in `zsh` and `fish`. You can 240 - also do `&|` to pipe both standard out and standard error at the same time in 241 - the same way you'd do `2>&1 | whatever`.](conversation://Cadey/enby) 266 + [Will that work in every shell?](conversation://Mara/hmm) 242 267 243 - That will put standard out and standard error to `foo.log` the same way that 244 - `2>&1 > foo.log` will. You can also use this with `>>`: 268 + [It's a bourne shell (`bash`) extension, but I've tested it in `zsh` and `fish`. 269 + You can also do `&|` to pipe both standard out and standard error at the same 270 + time in the same way you'd do `2>&1 | whatever`.](conversation://Cadey/enby) 271 + 272 + You can also use this with `>>`: 245 273 246 274 ``` 247 275 $ rustc foo.rs &>> foo.log ··· 265 293 266 294 [How do I redirect standard in to a file?](conversation://Mara/hmm) 267 295 268 - The answer there is not directly! There is a workaround in the form of a tool 269 - called `tee` which outputs its standard in to both standard out and a file. For 270 - example: 296 + Well, you don't. Standard in is an input, so you can change where it comes 297 + _from_, not where it goes. 298 + 299 + But, maybe you want to make a copy of a program's input and send it somewhere 300 + else. There is a way to do _that_ using a command called `tee`. `tee` copies 301 + its standard input to standard output, but it also writes a second copy to a 302 + file. For example: 271 303 272 304 ```console 273 305 $ dmesg | tee dmesg.txt | grep 'msedge' ··· 345 377 346 378 --- 347 379 348 - Thanks to violet spark for looking over this post and fact-checking as well as 349 - helping mend some of the brain dump and awkward wording into more polished 350 - sentences. 380 + Thanks to violet spark, cadence, and AstroSnail for looking over this post and 381 + fact-checking as well as helping mend some of the brain dump and awkward 382 + wording into more polished sentences.