I'll start off this blog with two super-cool bash shell tricks. You'll be the envy of your friends with these up your sleeve.
Bash does some super-cool magic when you access
/dev/tcp/hostname/port. It will create a TCP socket that is connected to the named host on the given port. This lets you easily use network sockets with regular shell IO redirection. For example, the following simply prints the time from NIST:
cat < /dev/tcp/time.nist.gov/13
And YES, you can read AND write to these sockets. Here's how. The following example fetches the source for the www.google.com homepage.
exec 5<> /dev/tcp/www.google.com/80
printf "GET / HTTP/1.0\n\n" >&5
Check out the
bash(1)manpage for more details.
This trick allows you to use a process *almost* anywhere you can use a file. To illustrate, let's consider the
diffcommand. Most versions of
diffrequire you to pass exactly two file names as arguments. But what if we want to diff something, like the contents of a directory, that doesn't necessarily exist in a file? This is where we can use process substitution. For example, to diff the contents of two directories, you could use:
diff <(find dir1) <(find dir2)
<(command)creates a named pipe, and attaches
command's STDOUT to the pipe. So, anything that reads from the pipe will actually be reading the output of command. To prove this to yourself, try the following:
$ echo <(/bin/true)
$ ls -l <(/bin/true)
lr-x------ 1 jgm eng 64 Jul 13 21:50 /dev/fd/63 -> pipe:
$ file <(/bin/true)
/dev/fd/63: broken symbolic link to pipe:
Similarly, you can use the syntax
>(command)to have the
commandread from the pipe. An example is:
tar cvf >(gzip -c > dir.tar.gz) dir
Obviously, there are better ways to accomplish taring and compressing, but the point was to use process substitution.