<?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/"
	xmlns:georss="http://www.georss.org/georss" xmlns:geo="http://www.w3.org/2003/01/geo/wgs84_pos#" xmlns:media="http://search.yahoo.com/mrss/"
	>

<channel>
	<title>All The Naughty Bits &#187; Perl</title>
	<atom:link href="http://rogerbush.wordpress.com/category/perl/feed/" rel="self" type="application/rss+xml" />
	<link>http://rogerbush.wordpress.com</link>
	<description>Programming Jiu-Jitsu for the Aspiring Linux Hacker</description>
	<lastBuildDate>Fri, 15 Aug 2008 18:07:19 +0000</lastBuildDate>
	<generator>http://wordpress.com/</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<cloud domain='rogerbush.wordpress.com' port='80' path='/?rsscloud=notify' registerProcedure='' protocol='http-post' />
<image>
		<url>http://www.gravatar.com/blavatar/584d8337c14375b7eec37c4fcfcb8b56?s=96&#038;d=http://s.wordpress.com/i/buttonw-com.png</url>
		<title>All The Naughty Bits &#187; Perl</title>
		<link>http://rogerbush.wordpress.com</link>
	</image>
	<atom:link rel="search" type="application/opensearchdescription+xml" href="http://rogerbush.wordpress.com/osd.xml" title="All The Naughty Bits" />
		<item>
		<title>Command line programs and perl Getopt::Long</title>
		<link>http://rogerbush.wordpress.com/2008/02/19/command-line-programs-and-perl-getoptlong/</link>
		<comments>http://rogerbush.wordpress.com/2008/02/19/command-line-programs-and-perl-getoptlong/#comments</comments>
		<pubDate>Tue, 19 Feb 2008 00:22:30 +0000</pubDate>
		<dc:creator>rogerbush</dc:creator>
				<category><![CDATA[Command Line]]></category>
		<category><![CDATA[Linux]]></category>
		<category><![CDATA[Perl]]></category>
		<category><![CDATA[command line option parsing]]></category>
		<category><![CDATA[linux command line utility]]></category>
		<category><![CDATA[linux perl scripting]]></category>
		<category><![CDATA[perl command line option parsing]]></category>
		<category><![CDATA[perl Getopt Long]]></category>
		<category><![CDATA[perl plain old documentation]]></category>
		<category><![CDATA[perl self documenting code]]></category>

		<guid isPermaLink="false">http://rogerbush.wordpress.com/?p=5</guid>
		<description><![CDATA[In Today&#8217;s Post
I provide a simple template I use to start every command-line utility I write in Perl.  We&#8217;ll also make command-line option parsing easy using Getopt::Long, as well as make encapsulated documentation using POD.
Perl, the Swiss Army Chainsaw 
Perl is an excellent language for system scripting. There are those who criticize Perl for [...]<img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rogerbush.wordpress.com&blog=2869039&post=5&subd=rogerbush&ref=&feed=1" />]]></description>
			<content:encoded><![CDATA[<div class='snap_preview'><br /><p><b>In Today&#8217;s Post</b></p>
<p>I provide a simple template I use to start every command-line utility I write in Perl.  We&#8217;ll also make command-line option parsing easy using Getopt::Long, as well as make encapsulated documentation using POD.</p>
<p><b>Perl, the Swiss Army Chainsaw </b></p>
<p>Perl is an excellent language for system scripting. There are those who criticize Perl for being &#8220;syntactically excessive.&#8221;  However, as languages evolve expressive power they often become more complicated.  Remaining backward compatible requires carrying around a certain amount of syntactic baggage.</p>
<p>I&#8217;m pragmatic in that I&#8217;d choose a language that was powerful with a few eccentricities over one that was perfect and less useful, or one that had stopped evolving.  Languages are a living thing &#8211; they need to adapt to changes in the environment or they die.</p>
<p>Perl will always be alive and well because it&#8217;s just too damn useful. Larry Wall, the creator of Perl, has described his creation variously as &#8220;duct tape for the Web&#8221; and a &#8220;Swiss Army chainsaw&#8221;.  Perl&#8217;s hallmark is flexibility, which is just what&#8217;s required to glue things together that weren&#8217;t necessarily designed to be glued together.</p>
<p>In a future post I&#8217;ll show you a style of Perl programming that works well for me and provides just the right amount of OOP without going overboard.  This is actually simpler to do than you might think.</p>
<p><span id="more-5"></span></p>
<p><b>Unix Command Line Utilities Are Reusable, System-Level Building Blocks</b></p>
<ol>
<li>One of the reasons Unix is so successful is the philosophy of &#8220;doing one thing really well.&#8221;  Command-line utilities are designed to address a single problem well.</li>
<li>A second reason Unix is so successful is the &#8220;building block approach&#8221; &#8211;  simple, well designed components can be connected together in various ways to solve a larger problem.</li>
<li>Unix command-line utilities should be thought of as reusable, system-level building blocks.</li>
<li>Write a command-line utility rather than a script.  This is a conceptual task, which requires a few simple steps.  One can often alter a script to turn it into a command-line utility.</li>
</ol>
<p>Note, when I say Unix here, I mean &#8220;Unix and all it&#8217;s related descendants&#8221;, such as Linux (I&#8217;m old school, deal).  I typically work with Linux (RHEL4, FC8) and FreeBSD (4 and 6).</p>
<p>I differentiate between scripts and command-line utilities.  I think of a script as being designed for a single purpose, whereas a command-line utility was (should be) a building block.  This is largely conceptual, and I realize it&#8217;s not a hard and fast rule, but it tends to be true.</p>
<p>I can&#8217;t count the number of times I&#8217;ve had to rewrite something someone wrote, just because they didn&#8217;t take the time to think of things from the perspective of reusability.  The template below solves a few problems in this area.</p>
<p><b>Parsing Options</b></p>
<p>Command-line utilities often have a plethora of options that fine tune their behavior.  For example the &#8220;ls&#8221; command has 36 &#8220;single character&#8221; options on OS X.  The reason for having so many options is related to the design principles I&#8217;ve already mentioned:  do one thing really well and make it so no one has to ever do it again (i.e. make it a building block).  &#8220;ls&#8221; is designed to be used interactively, as well as produce output that is consumed by other programs, and so modifying it&#8217;s output via options is important (less so today since languages like perl have their own internal methods of listing files, like globbing).</p>
<p>One of the annoying parts of writing a command-line utility is parsing options.  Options may have arguments, be different types, have valid and invalid ranges, and they need error checking.  It&#8217;s also useful to be able to print a list of them from the program (using -h, or &#8211;help).</p>
<p>The perl library Getopt::Long solves the problems I&#8217;ve just described in an elegant way.  In addition it&#8217;s got lots of extra bells and whistles for doing things like &#8220;repeated arguments&#8221;.  The template below uses Getopt::Long and demonstrates it&#8217;s power.</p>
<p><b>What does this code do?</b></p>
<p>The code below is a &#8220;starting template&#8221;.  I have a directory called &#8220;templates&#8221; which are simple program starting points for different purposes.  When I want to write a command-line utility, I copy the template and make changes.</p>
<ol>
<li>Command-line option parsing through Getopt::Long.</li>
<li>Internal documentation which can be programatically displayed, or formatted by other programs.  This is done with Perl&#8217;s POD format (Plain Old Documentation).</li>
<li>Basic error handling.</li>
<li>As a template, its purpose is to jog my memory so I don&#8217;t have to try to remember how to use Getopt::Long, or the correct format for POD.  Thus the code as-is doesn&#8217;t do too much (we&#8217;ll see how to use it below).</li>
</ol>
<p><a title="code" name="code"></a><b>Starting Template:  Unix Command Line Utility</b></p>
<div class="sc"> The Starting Template</p>
<pre>
<span class="comment-delimiter">#</span><span class="comment">!/usr/bin/perl
</span>
<span class="comment-delimiter"># </span><span class="comment">Use this "starter template" as a starting point for your
</span><span class="comment-delimiter"># </span><span class="comment">own cmdline utilities.  Shows how to use Getopt::Long for
</span><span class="comment-delimiter"># </span><span class="comment">option processing and POD for documentation.
</span><span class="comment-delimiter">#</span><span class="comment">
</span><span class="comment-delimiter"># </span><span class="comment">http://rogerbush.wordpress.com/2008/02/19/</span>
<span class="comment-delimiter"># </span><span class="comment">command-line-programs-and-perl-getoptlong/</span>

<span class="keyword">use</span> <span class="constant">strict</span>;
<span class="keyword">use</span> <span class="constant">warnings</span>;

<span class="keyword">use</span> <span class="constant">Getopt</span>::Long;
<span class="keyword">use</span> <span class="constant">Pod</span>::Usage;

<span class="keyword">sub</span> <span class="function-name">main</span>
{
    <span class="type">my</span> %<span class="underline"><span class="variable-name">options</span></span>;

    GetOptions
        (\%<span class="underline"><span class="variable-name">options</span></span>,
         <span class="string">'help|?'</span>,
         <span class="string">'length=i'</span>,
         <span class="string">'filename=s'</span>,
         <span class="string">'addr=s@'</span>,
         <span class="string">'man'</span>) or pod2usage (2);

    pod2usage (1) <span class="keyword">if</span> $<span class="variable-name">options</span>{help};
    pod2usage (-exitstatus =&gt; 0, -verbose =&gt; 2)
        <span class="keyword">if</span> $<span class="variable-name">options</span>{man};

    <span class="keyword">if</span> ($<span class="variable-name">options</span>{length})
    {
        pod2usage (<span class="string">"--length must be &gt; 0."</span>)
            <span class="keyword">unless</span> $<span class="variable-name">options</span>{length} &gt; 0;

        print <span class="string">"length is $options{length}\n"</span>;
    }

    print <span class="string">"filename is $options{filename}\n"</span>
        <span class="keyword">if</span> $<span class="variable-name">options</span>{filename};

    <span class="keyword">if</span> ($<span class="variable-name">options</span>{addr})
    {
        <span class="keyword">foreach</span> <span class="type">my</span> $<span class="variable-name">a</span> (@{${<span class="variable-name">options</span>{addr}}})
        {
            print <span class="string">"addr: $a\n"</span>;
        }
    }
}

main ();
__END__

<span class="comment">=head1 NAME

perlcmdline - A do nothing, starter template for implementing
command-line utilities.

=head1 SYNOPSIS

perlcmdline [options]

"perlcmdline --help" will list options.  "perlcmdline --man"
will show docs.

=head1 OPTIONS

=over 4

=item B&lt;--help&gt;

Print a brief help message and exits.

=item B&lt;--man&gt;

Prints the manual page and exits.

=item B&lt;--length positive-integer&gt;

A "do nothing" length value which must be an int &gt; 0.

=item B&lt;--filename input-filename&gt;

A "do nothing" string value.

=item B&lt;--addr hostname-or-ip&gt;

An internet address.  This option may be used multiple
times in a single command to specify multiple addresses.

=back

=head1 AUTHOR

Roger Bush, rogerbush8 at yahoo dot com

=head1 COPYRIGHT

Copyright (c) 2007 Roger Bush. All rights reserved. This
program is free software; you can redistribute it and/or
modify it under the same terms as Perl itself.

=cut

</span></pre>
</div>
<div class="cl"> The Naughty Bits</p>
<pre>
1. Getopt takes many forms.  In the form I'm using, I pass
   in a hash to hold all of the variables rather than assigning
   values to loose variables.
2. Getopt allows other types of inputs, such as hashes,
   flags, and several other types.  For a full list see the
   reference at the end of this post.
3. If a value is not specified, it will not be defined in the
   options hash (e.g. if ( ! defined $options{foo})).
4. The expression @{$options{addr}} evaluates to an array
   (it dereferences the array ref at $options{addr}.  Similarly
   %{hash_ref} would dereference a hash.
5. __END__ tells perl where the code has ended.  This always
   precedes the docs at the end which are called "POD" (Plain
   Old Documentation).  Perl's POD has special directives which
   start a new line with a "=name-of-directive".  See ref on
   POD at end of blog for more.
6. =over, and =back are POD indenting commands.  over
   indents the given number of spaces, and back goes back
   to the indenting setup prior to the over statement.
7. pod2usage prints out the SYNOPSIS and potentially
   the options in the POD section, when given a single
   numeric argument (1 is Usage, 2 is Options).  It can also
   be provided a hash of options affecting its behavior.</pre>
</div>
<p><a title="demo" name="demo"></a>Time to give the program a try.  Let&#8217;s try an unknown option to see how it handles it:</p>
<div class="cl">
<pre>
$ ./perlcmdline --foo
Unknown option: foo
Usage:
    perlcmdline [options]

    "perlcmdline --help" will list options. "perlcmdline --man"
    will show docs.</pre>
</div>
<p>It told us that &#8220;foo&#8221; was an &#8220;Unknown option&#8221; and then it printed out usage from the SYNOPSIS (POD) section.  This is the behavior of &#8220;pod2usage(2)&#8221;.  Note the helpful &#8220;&#8211;help&#8221; and &#8220;&#8211;man&#8221; info we added to SYNOPSIS.</p>
<p>Now let&#8217;s try the &#8220;&#8211;length&#8221; option without the argument (it requires a number):</p>
<div class="cl">
<pre>
$ ./perlcmdline --length
Option length requires an argument
Usage:
    perlcmdline [options]

    "perlcmdline --help" will list options. "perlcmdline --man"
    will show docs.</pre>
</div>
<p>Now let&#8217;s try a length that is equal to zero (we explicitly check for this and exit from the command-line):</p>
<div class="cl">
<pre>
$ ./perlcmdline --length 0
--length must be &gt; 0.
Usage:
    perlcmdline [options]

    "perlcmdline --help" will list options. "perlcmdline --man"
    will show docs.</pre>
</div>
<p>Now let&#8217;s try misspelling length (we&#8217;ll truncate it):</p>
<div class="cl">
<pre>
$ ./perlcmdline --len 5
length is 5</pre>
</div>
<p>Whoa, what happened there?  It turns out that Getopt automatically supports abbreviation.  It will use the string to match the longest match possible.</p>
<p>Let&#8217;s try &#8220;&#8211;help&#8221;:</p>
<div class="cl">
<pre>
./perlcmdline --help
Usage:
    perlcmdline [options]

    "perlcmdline --help" will list options. "perlcmdline --man"
    will show docs.

Options:
    --help
        Print a brief help message and exits.

    --man
        Prints the manual page and exits.

    --length positive-integer
        A "do nothing" length value which must be an int &gt; 0.

    --filename input-filename
        A "do nothing" string value.

    --addr hostname-or-ip
        An internet address.  This option may be used multiple
        times in a single command to specify multiple addresses.</pre>
</div>
<p>Very cool.  The options listed under (POD) OPTIONS got printed this time, due to pod2usage(1).  Try &#8220;&#8211;man&#8221; on your own.</p>
<p>Now, let&#8217;s try some legitimate options.</p>
<div class="cl">
<pre>
$ ./perlcmdline --filename bar --length 2 --addr 127.0.0.1
--addr 192.168.0.1
length is 2
filename is bar
addr: 127.0.0.1
addr: 192.168.0.1</pre>
</div>
<p>Note that the multiple options specified using &#8211;addr worked properly, as well as the other options.</p>
<p><b>Conclusion</b></p>
<p>Now you&#8217;ve got a template for creating command-line utilities that have embedded documentation and handle options with ease.  You should copy it and use it as a starting point whenever you want to write a script or command-line utility.  We&#8217;ve alsoseen the basics of using Getopt::Long, as well as basic POD, and pod2usage.</p>
<p>There are a few more important aspects to writing good command-line utilities that I&#8217;ll save for other posts.</p>
<p><b>References</b></p>
<ol>
<li><a href="http://perldoc.perl.org/Getopt/Long.html">Getopt::Long</a> docs at perldoc.perl.org</li>
<li><a href="http://perldoc.perl.org/pod2usage.html">pod2usage</a> docs at perldoc.perl.org</li>
<li><a href="http://perldoc.perl.org/perlpod.html">POD</a> docs at perldoc.perl.org</li>
</ol>
<img alt="" border="0" src="http://feeds.wordpress.com/1.0/categories/rogerbush.wordpress.com/5/" /> <img alt="" border="0" src="http://feeds.wordpress.com/1.0/tags/rogerbush.wordpress.com/5/" /> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gocomments/rogerbush.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/comments/rogerbush.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godelicious/rogerbush.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/delicious/rogerbush.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/gostumble/rogerbush.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/stumble/rogerbush.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/godigg/rogerbush.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/digg/rogerbush.wordpress.com/5/" /></a> <a rel="nofollow" href="http://feeds.wordpress.com/1.0/goreddit/rogerbush.wordpress.com/5/"><img alt="" border="0" src="http://feeds.wordpress.com/1.0/reddit/rogerbush.wordpress.com/5/" /></a> <img alt="" border="0" src="http://stats.wordpress.com/b.gif?host=rogerbush.wordpress.com&blog=2869039&post=5&subd=rogerbush&ref=&feed=1" /></div>]]></content:encoded>
			<wfw:commentRss>http://rogerbush.wordpress.com/2008/02/19/command-line-programs-and-perl-getoptlong/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
	
		<media:content url="http://0.gravatar.com/avatar/e9fee4f625317e26721c36555f2002da?s=96&#38;d=identicon" medium="image">
			<media:title type="html">rogerbush</media:title>
		</media:content>
	</item>
	</channel>
</rss>