opus7: submit a new article from Athas - tgtimes - The Gopher Times HTML git clone git://bitreich.org/tgtimes git://enlrupgkhuxnvlhsf6lc3fziv5h2hhfrinws65d7roiv6bfj7d652fid.onion/tgtimes DIR Log DIR Files DIR Refs DIR Tags DIR README --- DIR commit c8279e8b137436c61ad76e077afe0cec09ed9260 DIR parent 9c6672aaa881709d5e0139128423ad83000b557f HTML Author: Josuah Demangeon <me@josuah.net> Date: Sun, 16 Oct 2022 02:09:47 +0200 opus7: submit a new article from Athas Diffstat: A opus7/article-athas-shell-redirect… | 73 +++++++++++++++++++++++++++++++ 1 file changed, 73 insertions(+), 0 deletions(-) --- DIR diff --git a/opus7/article-athas-shell-redirections.mw b/opus7/article-athas-shell-redirections.mw @@ -0,0 +1,73 @@ +.SH athas +Shell Redirections +.2C 60 +. +.PP +Newcomers to the Unix shell quickly encounter handy tools such as +sed(1) and sort(1). This command prints the lines of the given file +to stdout, in sorted order: +. +.DS +$ sort numbers +.DE +. +.PP +Soon after, newcomers will also encounter shell redirection, by which +the output of these tools can conveniently be read from or stored in +files: +. +.DS +$ sort < numbers > numbers_sorted +.DE +. +.PP +Our new user, fascinated by the modularity of the Unix shell, may then +try the rather obvious possibility of having the input and output file +be the same: +. +.DS +$ sort < numbers > numbers +.DE +. +.PP +But disaster strikes: the file is empty! The user has lost their +precious collection of numbers - let's hope they had a backup. Losing +data this way is almost a rite of passage for Unix users, but let us +spell out the reason for those who have yet to hurt themselves this +way. +. +.PP +When the Unix shell evaluates a command, it starts by processing the +redirection operators - that's the '>' and '<' above. While '<' just +opens the file, '>' *truncates* the file in-place as it is opened for +reading! This means that the 'sort' process will dutifully read an +empty file, sort its non-existent lines, and correctly produce empty +output. +. +.PP +Some programs can be asked to write their output directly to files +instead of using shell redirection (sed(1) has '-i', and for sort(1) +we can use '-o'), but this is not a general solution, and does not +work for pipelines. Another solution is to use the sponge(1) tool +from the "moreutils" project, which stores its standard input in +memory before finally writing it to a file: +. +.DS +$ sort < numbers | sponge numbers +.DE +. +.PP +The most interesting solution is to take advantage of subshells, the +shell evaluation order, and Unix file systems semantics. When we +delete a file in Unix, it is removed from the file system, but any +file descriptors referencing the file remain valid. We can exploit +this behaviour to delete the input file *after* directing the input, +but *before* redirecting the output: +. +.DS +$ (rm numbers && sort > numbers) < numbers +.DE +. +.PP +This approach requires no dependencies and will work in any Unix +shell.