Subshells

Unix shells allow subshells, which can aggregate output from multiple commands into a single stream, or pass input to multiple commands. Aggregation allows the output from two commands to be piped into a single e-mail:

$ (echo data; echo otherdata) | mail nobody@example.org

Use the normally useless cat(1) command to join compressed and uncompressed log data together for searching:

$ ( gunzip -c log.2006-09-01.gz; cat log ) | grep …

When passing a single stream to multiple commands, typically only one of those commands handles the input. In the following example, cd ignores standard input, but does change the working directory for the subsequent mkdir. When the subshell exits, the working directory will not have been changed in the parent shell.

$ rpm2cpio some.rpm | ( cd SOURCES && cpio -id 2>/dev/null )

Note the use of &&. A cd SOUCES; cpio … semicolon between the commands will ignore any chdir(2) errors, and blindly run the cpio(1). By using &&, the cpio will only be called if the chdir succeeds. Always check the exit status of every chdir call made.

To learn more, use pwd(1) to show the current working directory:

$ cd /var/tmp; pwd | ( cat; cd /tmp && pwd ); pwd /var/tmp /tmp /var/tmp

If the command to run only accepts one argument, use either a shell loop, or xargs(1).

$ ( echo dir1; echo dir2 ) | ( cd /tmp && xargs mkdir ) $ ls -d /tmp/dir* /tmp/dir1 /tmp/dir2 $ rmdir /tmp/dir*

A shell loop allows multiple commands:

$ ( echo dir1; echo dir2 ) | \ ( cd /tmp && while read dir; do \ mkdir $dir; chmod 700 $dir; done )

However, increasing complexity on the command line at some point mandates a wrapper script to encapsulate the logic. This provides an easy to edit file that can be tested, have appropriate input checks and error handling, and be saved under a version control repository.

Technorati Tags: