The bash shell is also a pretty handy programming language. One way to use this is writing scripts. However, another use is writing ad-hoc, one-time-use programs, for very specific tasks, right on the command line. I do this a lot, and find myself using the same techniques over and over.
In this post, I'll share some useful command-line techniques for redirection.
There are many ways other than pipes for redirecting stdin and stdout:
cmd &>file: send both stdout and stderr ofcmdtofile. Equivalent tocmd >file 2>&1.cmd <file: pipes the contents offileintocmd. Similar tocat file | cmd, except that while pipes execute in a subshell with their own scope, this keeps everything in the same scope.cmd <<<word: expandswordand pipes it intocmd.wordcan be anything you'd type as a program argument. For example,cmd <<<$VARpipes the value of$VARintocmd.
Also, sometimes programs need arguments on the command line, rather than through stdin:
cmd $(<file): expands the contents offileas arguments tocmd. For example, if the filetoRemovecontains a list of files,rm $(<toRemove)removes those files.cmd1 <(cmd2): creates a temporary file containing the output ofcmd2, then puts the name of that file as an argument tocmd1. This is handy whencmd1expects filename arguments. For example, to see the difference between the contents of directoriesdir1anddir2, usediff <(ls dir1) <(ls dir2). This is conceptually equivalent tols dir1 >/tmp/contentsDir1 ls dir2 >/tmp/contentsDir2 diff /tmp/contentsDir1 /tmp/contentsDir2 rm /tmp/contentsDir1 /tmp/contentsDir2
(only conceptually, though, since it actually uses fifos). For another handy command for this, check out comm.
Finally, you sometimes want to redirect to and from multiple programs at once:
{cmd1; cmd2; cmd3;} | cmd: pipes output ofcmd1,cmd2, andcmd3tocmd.cmd | tee >(cmd1) >(cmd2) >(cmd3) >/dev/null: pipes output ofcmdtocmd1,cmd2, andcmd3in parallel. This trick is a tweak on that here. In the same way<(cmd)is replaced with a file containing the stdout ofcmd,>(cmd)is replaced with a file that becomes the stdin ofcmd. Sinceteewrites its stdin to each given file, you can combine it with>(cmd)to send the output of one command to the stdin of many. The final>/dev/nulldiscards the stdout of tee, which we no longer need. Doesn't come up too often, but it's certainly neat.


No comments:
Post a Comment