<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Masterzen's Blog &#187; zsh</title>
	<atom:link href="http://www.masterzen.fr/category/system-administration/zsh-system-administration/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.masterzen.fr</link>
	<description>Journey in a software world...</description>
	<lastBuildDate>Sat, 31 Jul 2010 15:48:27 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>In love with zsh, part 1</title>
		<link>http://www.masterzen.fr/2009/04/19/in-love-with-zsh-part-one/</link>
		<comments>http://www.masterzen.fr/2009/04/19/in-love-with-zsh-part-one/#comments</comments>
		<pubDate>Sun, 19 Apr 2009 19:03:55 +0000</pubDate>
		<dc:creator>masterzen</dc:creator>
				<category><![CDATA[System Administration]]></category>
		<category><![CDATA[zsh]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[shell]]></category>
		<category><![CDATA[unix]]></category>

		<guid isPermaLink="false">http://www.masterzen.fr/?p=26</guid>
		<description><![CDATA[Note: when I started writing this post, I didn&#8217;t know it would be this long.
I decided then to split it in several posts, each one covering one or more interesting aspect of zsh.
You&#8217;re now reading part 1.
I first used a Unix computer in 1992 (it was running SunOS 4.1 if I remember correctly).
I&#8217;m using Linux [...]]]></description>
			<content:encoded><![CDATA[<p><strong>Note</strong>: when I started writing this post, I didn&#8217;t know it would be this long.<br />
I decided then to split it in several posts, each one covering one or more interesting aspect of zsh.<br />
You&#8217;re now reading <em>part 1</em>.</p>
<p>I first used a <a href="http://en.wikipedia.org/wiki/Unix" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">Unix</a> computer in 1992 (it was running <a href="http://en.wikipedia.org/wiki/SunOS" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">SunOS 4.1</a> if I remember correctly).<br />
I&#8217;m using <a href="http://www.kernel.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.kernel.org');">Linux</a> since 1999 (after using <a href="http://en.wikipedia.org/wiki/OpenVMS" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">VMS</a> throughout the 90s in school, but I left the Unix world while I was working with RAYflect doing 3D stuff on Mac and Windows).</p>
<p>During the time I worked with those various unices (including <a href="http://en.wikipedia.org/wiki/Irix" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">Irix</a> on a <a href="http://www.futuretech.blinkenlights.nl/crimson.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/www.futuretech.blinkenlights.nl');">Crimson</a>), I think I&#8217;ve used almost every possible shell with various level of pleasure and expertise, including but not limited to:</p>
<ul>
<li><a href="http://en.wikipedia.org/wiki/Tcsh" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">tcsh</a></li>
<li><a href="http://en.wikipedia.org/wiki/Korn_shell" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">ksh</a></li>
<li><a href="http://en.wikipedia.org/wiki/Bash" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">bash</a></li>
<li><a href="http://en.wikipedia.org/wiki/Zsh" onclick="javascript:pageTracker._trackPageview('/outbound/article/en.wikipedia.org');">zsh</a></li>
</ul>
<p>When my own road crossed ZSH (about 6 years ago), I felt in love with this powerful shell, and it&#8217;s now my default shell on my servers, workstations and of course my macbook laptop.</p>
<p>The point of this blog post is to give you an incentive to switch from <em>insert random shell</em> here to <strong>zsh</strong> and never turn back.</p>
<p>The whole issue with <strong>zsh</strong> is that the usual random Linux distribution ships with Bash by default (that&#8217;s not really, true as <a href="http://grml.org/" onclick="javascript:pageTracker._trackPageview('/outbound/article/grml.org');">GRML</a> ships with zsh, and a good configuration). And Bash does its job well enough and is wide-spread, that people have usually only low incentive to switch to something different. I&#8217;ll try to let you see why <strong>zsh</strong> is worth the little investment.</p>
<h2>Which version should I run?</h2>
<p>Right now, zsh exists in 2 versions a stable one (4.2.7) and a development one (4.3.9).<br />
I&#8217;m of course running the development version (I usually prefer seeing new bugs than old bugs <img src='http://www.masterzen.fr/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> )</p>
<p>I recommend using the development version.</p>
<h2>UTF-8 support, anyone?</h2>
<p>Some people don&#8217;t want to switch to zsh because they think zsh doesn&#8217;t support UTF-8. That&#8217;s plain wrong, if you follow my previous advice which is to run a version greater than 4.3.6, UTF-8 support is there and works really fine.</p>
<h2>Completion</h2>
<p>One of the best thing in zsh is the <em>TAB completion</em>. It&#8217;s certainly the best <em>TAB completion</em> I could use in every shell I tried. It can completes almost anything, from <em>files</em> (of course), to <em>users</em>, including but not limited to <em>hosts</em>, <em>command options</em>, <em>package names</em>, <em>git revisions/branches</em> etc.</p>
<p><strong>Zsh</strong> ships with completions for almost every shipped apps on earth. And the beauty is that completion is so much configurable that you can twist it to your own specific taste.</p>
<p>To activate completion on your setup:</p>
<pre class="syntax-highlight:sh">
% zmodload zsh/complist
% autoload -U compinit &amp;&amp; compinit
</pre>
<p>The completion system is completely configurable. To configure it we use the zstyle command:</p>
<pre class="syntax-highlight:sh">
  zstyle &lt;context&gt; &lt;styles&gt;
</pre>
<p>How does it work?</p>
<p>The context defines where the style will apply. The context is a string of &#8216;:&#8217; separated strings:<br />
&#8216;:completion:function:completer:command:argument:tag&#8217;<br />
Some part can be replaced by *, so that &#8216;:completion:*&#8217; is the least specific context.<br />
More specific context wins over less specific ones of course.</p>
<p>The various styles selects the options to activate (see below).</p>
<p>If you want to learn more about zsh completion, please <a href="http://zsh.sourceforge.net/Doc/Release/zsh_19.html" onclick="javascript:pageTracker._trackPageview('/outbound/article/zsh.sourceforge.net');">read the zsh section completion manual</a>.</p>
<p>Zsh completion is also:</p>
<h3>Formatting completion</h3>
<p>When zsh needs to display completion matches or errors, it uses the format style for doing so.</p>
<pre class="syntax-highlight:sh">
  zstyle &#039;:completion:*&#039; format &#039;Ouch: %d <img src='http://www.masterzen.fr/wp-includes/images/smilies/icon_smile.gif' alt=':-)' class='wp-smiley' /> &#039;
</pre>
<p>%d will be replaced by the actual text zsh would have been printed if no format style were applied.<br />
You can use the same escape sequences as in zsh prompts.</p>
<p>Since there are many different types of messages, it is possible to restrict to warnings or messages by changing<br />
the <em>tags</em> part of the context:</p>
<pre class="syntax-highlight:sh">
  zstyle &#039;:completion:*:warnings&#039; format &#039;Too bad there is nothing&#039;
</pre>
<h3><img class="aligncenter size-medium wp-image-29" title="format-warnings" src="http://www.masterzen.fr/wp-content/uploads/2009/04/format-warnings.jpg" alt="" width="209" height="56" /></h3>
<p>And since it is possible to use all the prompt escapes, you can add style to the formats:</p>
<pre class="syntax-highlight:sh">
# format all messages not formatted in bold prefixed with ----
zstyle &#039;:completion:*&#039; format &#039;%B---- %d%b&#039;
# format descriptions (notice the vt100 escapes)
zstyle &#039;:completion:*:descriptions&#039;    format $&#039;%{\e[0;31m%}completing %B%d%b%{\e[0m%}&#039;
# bold and underline normal messages
zstyle &#039;:completion:*:messages&#039; format &#039;%B%U---- %d%u%b&#039;
# format in bold red error messages
zstyle &#039;:completion:*:warnings&#039; format &quot;%B$fg[red]%}---- no match for: $fg[white]%d%b&quot;
</pre>
<p>And the result:</p>
<h3>Grouping completion</h3>
<p>By default matches comes in no specific order (or in the order they&#8217;ve been found).<br />
It is possible to separate the matches in distinct related groups:</p>
<pre class="syntax-highlight:sh">
  # let&#039;s use the tag name as group name
  zstyle &#039;:completion:*&#039; group-name &#039;&#039;
</pre>
<p>An example of groups:<br />
<a href="http://www.masterzen.fr/wp-content/uploads/2009/04/group-name.jpg" ><img class="aligncenter size-medium wp-image-30" title="group-name" src="http://www.masterzen.fr/wp-content/uploads/2009/04/group-name-300x130.jpg" alt="Grouping matches" width="300" height="130" /></a></p>
<h3>Menu completion</h3>
<p>Menu completion is when you press TAB several times and the completion changes to cycle through the available matches. By default in zsh, menu completion activates the second time you press the TAB key (the first one triggered the first completion).</p>
<h3>Menu selection</h3>
<p>Menu selection is when zsh displays below your prompt the list of possible selections arranged by categories.</p>
<p>A short drawing is always better than thousands words, so hop an example:</p>
<p style="text-align: center;"><a href="http://www.masterzen.fr/wp-content/uploads/2009/04/menu-selection.jpg" ><img class="alignnone size-full wp-image-27 aligncenter" title="menu-selection" src="http://www.masterzen.fr/wp-content/uploads/2009/04/menu-selection.jpg" alt="Menu Selection - here I\'m cycling through gzip options" width="499" height="240" /></a></p>
<p>In this example I typed gzip -&lt;TAB&gt; then navigated with the arrows to &#8211;stdout.</p>
<p>To activate menu selection:</p>
<pre class="syntax-highlight:sh">
  # activate menu selection
  zstyle &#039;:completion:*&#039; menu select
</pre>
<h3>There&#8217;s also approximate completion</h3>
<p>With this, zsh corrects what you already have typed.<br />
Approximate completion is controlled by the</p>
<pre>_approximate</pre>
<p>completer.<br />
Approximate completion looks first for matches that differs by one error (configurable) to what you typed.<br />
An error can be either a transposed character, a missing character or an additional character.<br />
If some corrected entries are found they are added as matches, if none are found, the system continues with 2 errors and so on.<br />
Of course, you want it to stop at some level (use the max-errors completion style).</p>
<pre class="syntax-highlight:sh">
  # activate approximate completion, but only after regular completion (_complete)
  zstyle &#039;:completion:::::&#039; completer _complete _approximate
  # limit to 2 errors
  zstyle &#039;:completion:*:approximate:*&#039; max-errors 2
  # or to have a better heuristic, by allowing one error per 3 character typed
  # zstyle &#039;:completion:*:approximate:*&#039; max-errors &#039;reply=( $(( ($#PREFIX+$#SUFFIX)/3 )) numeric )&#039;
</pre>
<h3>Completion of about everything</h3>
<p>From X windows, to hosts from users, almost everything including shell variables can be completed or menu-selected.</p>
<p>Here I typed &#8220;echo $PA&lt;TAB&gt;&#8221; and navigated to PATH:</p>
<p><img class="aligncenter size-full wp-image-28" title="var-completion" src="http://www.masterzen.fr/wp-content/uploads/2009/04/var-completion.jpg" alt="Variable Completion" width="207" height="69" /></p>
<p>Now, one thing that is extremely useful is completion of hosts:</p>
<pre class="syntax-highlight:sh">
# let&#039;s complete known hosts and hosts from ssh&#039;s known_hosts file
basehost=&quot;host1.example.com host2.example.com&quot;
hosts=($((
( [ -r .ssh/known_hosts ] &amp;&amp; awk &#039;{print $1}&#039; .ssh/known_hosts | tr , &#039;\n&#039;);\
echo $basehost; ) | sort -u) )

zstyle &#039;:completion:*&#039; hosts $hosts
</pre>
<h2>Aliases</h2>
<p>Yeah, I see, you&#8217;re wondering, aliases, pffuuuh, every shell on earth has aliases.</p>
<p>Yes, but does your average shell has global or suffix aliases?</p>
<h3>Suffix Aliases</h3>
<p>Suffix aliases are aliases that matches the end of the command-line.</p>
<p>Ex:</p>
<pre class="syntax-highlight:sh">
% alias -s php=nano
</pre>
<p>Now, I just have to write:</p>
<pre class="syntax-highlight:sh">
% index.php
</pre>
<p>And zsh executes nano index.php. Clever isn&#8217;t it?</p>
<h3>Global Aliases</h3>
<p>Global aliases are aliases that match anywhere in the command line.</p>
<p>Typical uses are:</p>
<pre class="syntax-highlight:sh">
  % alias -g G=&#039;| grep
  % alias -g WC=&#039;| wc -l&#039;
  % alias -g TF=&#039;| tail -f&#039;
  % alias -g DN=&#039;/dev/null&#039;
</pre>
<p>Now, you just have to issue:</p>
<pre class="syntax-highlight:sh">
% ps auxgww G firefox
</pre>
<p>to find all firefox processes. Still not convinced?</p>
<h3>Too risky?</h3>
<p>Some might argue that global aliases are risky because zsh can change your command line behind your back if you need to have let&#8217;s say a capital G in there.</p>
<p>Because of this I&#8217;m using the GRML way: I use a special key combination (see in an upcoming post about key binding) that auto-completes my aliases directly on the command line, without defining a global alias.</p>
<h2>Globbing</h2>
<p>One of the best feature, albeit one of the more difficult to master is zsh extended globing.</p>
<p>Globbing is the process of matching several files or paths with an expression. The most usually known forms are * or ?, like: *.c to match every file ending with .c.</p>
<p>Zsh pushes the envelop far away, supporting the following:</p>
<p>Let&#8217;s say our current directory contains:</p>
<pre>  test.c
  test.h
  test.1
  test.2
  test.3
  a/a.txt
  b/1/b.txt
  b/2/d.txt
  team.txt
  term.txt</pre>
<h3>Wildcard: *</h3>
<p>This is the well known wildcard. It matches any amount of characters.<br />
As in:</p>
<pre class="syntax-highlight:sh">
% echo *.c
test.c
</pre>
<h3>Wildcard: ?</h3>
<p>This matches only one character.<br />
As in:</p>
<pre class="syntax-highlight:sh">
% echo test.?
test.c test.h
</pre>
<h3>Character classes: [...]</h3>
<p>This is a character class. It matches any character listed between the braces.<br />
The content can be either single characters:</p>
<blockquote><p>[abc0123] will match either a,b,c,0,1,2,3</p></blockquote>
<p>or range of characters:</p>
<blockquote><p>[a-e] will match from a to e inclusive</p></blockquote>
<p>or POSIX character classes</p>
<blockquote><p>[[:space:]] will match only spaces (refer to zshexpn(1) for more information)</p></blockquote>
<p>The character classes can be negated by a leading ^:</p>
<blockquote><p>[^abcd] matches only character outside of a,b,c,d</p></blockquote>
<p>If you need to list &#8211; or ], it should be the first character of the class. If you need both list ] first.</p>
<p>Example:</p>
<pre class="syntax-highlight:sh">
% echo test.[ch]
test.c test.h
</pre>
<h3>Number ranges &lt;x-y&gt;</h3>
<p>x and/or y can be omitted to have an open-ended range.<br />
&lt;-&gt; match all numbers.</p>
<pre class="syntax-highlight:sh">
% echo test.&lt;0-10&gt;
test.1 test.2 test.3
</pre>
<pre class="syntax-highlight:sh">
% echo test.&lt;2-&gt;
test.2 test.3
</pre>
<h3>Recursive matching: **</h3>
<p>You know find(1), but did you know you can do almost everything you need with only zsh?</p>
<pre class="syntax-highlight:sh">
% echo **/*.txt
a/a.txt b/1/b.txt b/2/d.txt
</pre>
<h3>Alternatives: (a|b)</h3>
<p>Matches either <em>a</em> or <em>b</em>. <em>a</em> and <em>b</em> can be any globbing expressions of course.</p>
<pre class="syntax-highlight:sh">
% echo test.(1|2)
test.1 test.2
% echo test.(c|&lt;1-2&gt;)
test.1 test.2 test.c
</pre>
<h3>Negated matches ^ (only with extended globbing)</h3>
<p>There are two possibilities:</p>
<blockquote><p>leading ^: as in ^*.o which selects every file except those ending with .o</p></blockquote>
<blockquote><p>pattern1^pattern2: pattern1 will be matched as a prefix, then anything not matching pattern2 will be selected</p></blockquote>
<pre class="syntax-highlight:sh">
% ls te*
test.c test.h team.txt term.txt
% echo te^st.*
team.txt term.txt
</pre>
<p>If you use the negation in the middle of a path section, the negation only applies to this path part:</p>
<pre class="syntax-highlight:sh">
% ls /usr/^bin/B*
/usr/lib/BuildFilter  /usr/sbin/BootCacheControl
</pre>
<h3>Pattern exceptions (~)</h3>
<p>Pattern exceptions are a way to express: &#8220;match this pattern, but not this one&#8221;.</p>
<pre class="syntax-highlight:sh">
# let&#039;s match all files except .svn dirs
% print -l **/*~*/.svn/* | grep &quot;.svn&quot;
# an nothing prints out, so that worked
</pre>
<p>It is to be noted that * after the ~ matches a path, not a single directory like the regular wildcard.</p>
<h3>Globbing qualifiers</h3>
<p>zsh allows to further restrict matches on file meta-data and not only file name, with the globbing qualifiers.</p>
<p>The globbing qualifier is placed in () after the expression:</p>
<pre class="syntax-highlight:sh">
# match a regular file with (.)
% print -l *(.)
</pre>
<p>We can restrict by:</p>
<ul>
<li><strong>(.)</strong>: regular files</li>
<li><strong>(/)</strong>: directories</li>
<li><strong>(*)</strong>: executables</li>
<li><strong>(@)</strong>: symbolic links</li>
<li><strong>(R),(W),(X),(U)</strong>: file permissions</li>
<li><strong>(LX),(L+X),(L-X),(LmX)</strong>: file size, with X in bytes, + for larger than files, &#8211; for smaller than files, m<br />
can be modifier for size (k for KiB, m for MiB)</li>
<li><strong>(mX),(m+X),(m-X)</strong>: matches file modified &#8220;more than X days ago&#8221;. A modifier can be used to express X in hours (h), months (M), wweks (W)&#8230;</li>
<li><strong>(u{owner})</strong>: a specific file <em>owner</em></li>
<li><strong>(f{permission string ala chmod})</strong>: a specific file <em>permissions</em></li>
</ul>
<pre class="syntax-highlight:sh">
% ls -al
total 0
drwxr-xr-x  8 brice wheel 272 2009-04-14 18:59 .
drwxrwxrwt 11 root  wheel 374 2009-04-14 20:04 ..
-rw-r--r--  1 root  wheel   0 2009-04-14 18:59 test.c
-rw-r--r--  1 brice wheel  10 2009-04-14 18:59 test.h
-rw-r--r--  1 brice wheel  20 2009-04-12 16:30 old
# match only files we own
% print -l *(U)
test.h
# match only file whose size less than 2 bytes
% print -l *(L-2)
test.c
# match only files older than 2 days
% print -l *(m-2)
old
</pre>
<p>It is possible to combine and/or negate several qualifiers in the same expressions</p>
<pre class="syntax-highlight:sh">
# print executable I can read but not write
% echo *(*r^w)
</pre>
<p>And there&#8217;s more, you can change the sort order, add a trailing distinctive character (ala ls -F).<br />
Refer to zshexpn(1) for more information.</p>
<h2>What&#8217;s next</h2>
<p>In the next post, I&#8217;ll talk about some other interesting things:</p>
<ul>
<li>History</li>
<li>Prompts</li>
<li>Configuration, options and startup files</li>
<li>ZLE: the line editor</li>
<li>Redirections</li>
<li>VCS info, and git in your prompt</li>
</ul>
<h2>newcomers, use GRML</h2>
<p>But that&#8217;s all for the moment.<br />
Newcomer, new switchers, if you want to get bootstrapped in a glimpse, I recommend using the GRML<br />
configuration:</p>
<pre class="syntax-highlight:sh">
# IMPORTANT: please note that you might override an existing
# configuration file in the current working directory!
wget -O ~/.zshrc http://git.grml.org/f/grml-etc-core/etc/zsh/zshrc
</pre>
]]></content:encoded>
			<wfw:commentRss>http://www.masterzen.fr/2009/04/19/in-love-with-zsh-part-one/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>

<!-- Dynamic Page Served (once) in 0.231 seconds -->
