Command substitution in zsh can take two forms.  In the traditional
form, a command enclosed in backquotes (`...`) is replaced on the
command line with its output.  This is the form used by the older
shells.  Newer shells (like zsh) also provide another form,
$(...).  This form is much easier to nest.
% ls -l `echo /vmunix`
-rwxr-xr-x  1 root      1209702 May 14 19:04 /vmunix
% ls -l $(echo /vmunix)
-rwxr-xr-x  1 root      1209702 May 14 19:04 /vmunix
% who | grep mad
subbarao ttyt7   May 23 15:02   (mad55sx15.Prince)
pfalstad ttyu1   May 23 16:25   (mad55sx14.Prince)
subbarao ttyu6   May 23 15:04   (mad55sx15.Prince)
pfalstad ttyv3   May 23 16:25   (mad55sx14.Prince)
% who | grep mad | awk '{print $2}'
ttyt7
ttyu1
ttyu6
ttyv3
% cd /dev; ls -l $(who |
> grep $(echo mad) |
> awk '{ print $2 }')
crwx-w----  1 subbarao  20,  71 May 23 18:35 ttyt7
crw--w----  1 pfalstad  20,  81 May 23 18:42 ttyu1
crwx-w----  1 subbarao  20,  86 May 23 18:38 ttyu6
crw--w----  1 pfalstad  20,  99 May 23 18:41 ttyv3
Many common uses of command substitution, however, are superseded by other mechanisms of zsh:
% ls -l `tty` crw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc % ls -l $TTY crw-rw-rw- 1 root 20, 28 May 23 18:35 /dev/ttyqc % ls -l `which rn` -rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn % ls -l =rn -rwxr-xr-x 1 root 172032 Mar 6 18:40 /usr/princeton/bin/rn
A command name with a = prepended is replaced with its full pathname. This can be very convenient. If it's not convenient for you, you can turn it off:
% ls =foo =bar % ls =foo =bar zsh: foo not found % setopt noequals % ls =foo =bar =foo =bar
Another nice feature is process substitution:
% who | fgrep -f =(print -l root lemke shgchan subbarao) root console May 19 10:41 lemke ttyq0 May 22 10:05 (narnia:0.0) lemke ttyr7 May 22 10:05 (narnia:0.0) lemke ttyrd May 22 10:05 (narnia:0.0) shgchan ttys1 May 23 16:52 (gaudi.Princeton.) subbarao ttyt7 May 23 15:02 (mad55sx15.Prince) subbarao ttyu6 May 23 15:04 (mad55sx15.Prince) shgchan ttyvb May 23 16:51 (gaudi.Princeton.)
A command of the form =(...) is replaced with the name of a
file containing its output.  (A command substitution, on the
other hand, is replaced with the output itself.)  print -l is
like echo, excepts that it prints its arguments one per line, the
way fgrep expects them:
% print -l foo bar foo bar
We could also have written:
% who | fgrep -f =(echo 'root > lemke > shgchan > subbarao')
Using process substitution, you can edit the output of a command:
% ed =(who | fgrep -f ~/.friends) 355 g/lemke/d w /tmp/filbar 226 q % cat /tmp/filbar root console May 19 10:41 shgchan ttys1 May 23 16:52 (gaudi.Princeton.) subbarao ttyt7 May 23 15:02 (mad55sx15.Prince) subbarao ttyu6 May 23 15:04 (mad55sx15.Prince) shgchan ttyvb May 23 16:51 (gaudi.Princeton.)
or easily read archived mail:
% mail -f =(zcat ~/mail/oldzshmail.Z) "/tmp/zsha06024": 84 messages, 0 new, 43 unread > 1 U TO: pfalstad, zsh (10) 2 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3 3 U JAM%TPN@utrcgw.utc.com, zsh fix (15) 4 U djm@eng.umd.edu, way to find out if running zsh? (25) 5 U djm@eng.umd.edu, Re: way to find out if running zsh? (17) 6 r djm@eng.umd.edu, Meta . (18) 7 U jack@cs.glasgow.ac.uk, Re: problem building zsh (147) 8 U nytim!tim@uunet.uu.net, Re: Zsh on Sparc1 /SunOS 4.0.3 9 ursa!jmd, Another fix... (61) 10 U pplacewa@bbn.com, Re: v18i084: Zsh 2.00 - A small complaint (36) 11 U lubkin@cs.rochester.edu, POSIX job control (34) 12 U yale!bronson!tan@uunet.UU.NET 13 U brett@rpi.edu, zsh (36) 14 S subbarao, zsh sucks!!!! (286) 15 U snibru!d241s008!d241s013!ala@relay.EU.net, zsh (165) 16 U nytim!tim@uunet.UU.NET, Re: Zsh on Sparc1 /SunOS 4.0.3 17 U subbarao, zsh is a junk shell (43) 18 U amaranth@vela.acs.oakland.edu, zsh (33) 43u/84 1: x % ls -l /tmp/zsha06024 /tmp/zsha06024 not found
Note that the shell creates a temporary file, and deletes it when the command is finished.
% diff =(ls) =(ls -F) 3c3 < fortune --- > fortune* 10c10 < strfile --- > strfile*
If you read zsh's man page, you may notice that <(...) is another
form of process substitution which is similar to =(...).  There
is an important difference between the two.  In the <(...) case,
the shell creates a named pipe (FIFO) instead of a file.  This is
better, since it does not fill up the file system; but it does not work
in all cases.  In fact, if we had replaced =(...) with
<(...) in the examples above, all of them would have stopped
working except for fgrep -f <(...).  You can not edit a pipe, or
open it as a mail folder; fgrep, however, has no problem with
reading a list of words from a pipe.  You may wonder why diff
<(foo) bar doesn't work, since foo | diff - bar works; this is
because diff creates a temporary file if it notices that one of
its arguments is -, and then copies its standard input to the
temporary file.