article-athas-shell-redirections.md - tgtimes - The Gopher Times | |
git clone git://bitreich.org/tgtimes git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws… | |
Log | |
Files | |
Refs | |
Tags | |
README | |
--- | |
article-athas-shell-redirections.md (2124B) | |
--- | |
1 # Shell Redirections by athas | |
2 | |
3 Newcomers to the Unix shell quickly encounter handy tools such as | |
4 sed(1) and sort(1). This command prints the lines of the given file | |
5 to stdout, in sorted order: | |
6 | |
7 $ sort numbers | |
8 | |
9 Soon after, newcomers will also encounter shell redirection, by which | |
10 the output of these tools can conveniently be read from or stored in | |
11 files: | |
12 | |
13 $ sort < numbers > numbers_sorted | |
14 | |
15 Our new user, fascinated by the modularity of the Unix shell, may then | |
16 try the rather obvious possibility of having the input and output file | |
17 be the same: | |
18 | |
19 $ sort < numbers > numbers | |
20 But disaster strikes: the file is empty! The user has lost their | |
21 precious collection of numbers - let's hope they had a backup. Losing | |
22 data this way is almost a rite of passage for Unix users, but let us | |
23 spell out the reason for those who have yet to hurt themselves this | |
24 way. | |
25 | |
26 When the Unix shell evaluates a command, it starts by processing the | |
27 redirection operators - that's the '>' and '<' above. While '<' just | |
28 opens the file, '>' *truncates* the file in-place as it is opened for | |
29 reading! This means that the 'sort' process will dutifully read an | |
30 empty file, sort its non-existent lines, and correctly produce empty | |
31 output. | |
32 | |
33 Some programs can be asked to write their output directly to files | |
34 instead of using shell redirection (sed(1) has '-i', and for sort(1) | |
35 we can use '-o'), but this is not a general solution, and does not | |
36 work for pipelines. Another solution is to use the sponge(1) tool | |
37 from the "moreutils" project, which stores its standard input in | |
38 memory before finally writing it to a file: | |
39 | |
40 $ sort < numbers | sponge numbers | |
41 | |
42 The most interesting solution is to take advantage of subshells, the | |
43 shell evaluation order, and Unix file systems semantics. When we | |
44 delete a file in Unix, it is removed from the file system, but any | |
45 file descriptors referencing the file remain valid. We can exploit | |
46 this behaviour to delete the input file *after* directing the input, | |
47 but *before* redirecting the output: | |
48 | |
49 $ (rm numbers && sort > numbers) < numbers | |
50 | |
51 This approach requires no dependencies and will work in any Unix | |
52 shell. |