<h1 id="bash-snippet---nullglob">Bash snippet - nullglob</h1>
<p>I recently did an HPR show about <a href="https://hackerpublicradio.org/eps.php?id=2278" title="Some supplementary Bash tips">Bash filename expansion</a> and described the '<code>shopt</code>' command and its options. One of the options I talked about was '<code>nullglob</code>' which controls what is returned from an expansion when no files match.</p>
<p>When '<code>nullglob</code>' is enabled, and a pattern does not match, nothing is returned. When it is disabled (the default) then the pattern itself is returned.</p>
<p>Although I didn't think I'd ever need to, I recently wrote a script where I used '<code>nullglob</code>', and thought I would share a snippet of the code to demonstrate what I did.</p>
<p>The script is for managing mail messages containing tag and summary updates. I use Thunderbird for my mail and have configured it to drop these messages into a directory so I can process them. I use Thunderbird's message filters to do this. A certain amount of Spam is also received, and sometimes valid messages need a bit of work before they can be processed.</p>
<p>The directory where the messages are saved (the spool area) is stored in the variable '<code>MAILDROP</code>' earlier in the script.</p>
<pre><code>  1 #
  2 # Find the files and store their names in an array. Use &#39;nullglob&#39; so we get
  3 # nothing when there is nothing, then revert to the original setting
  4 #
  5 NG=&quot;$(shopt -p nullglob)&quot;
  6 shopt -s nullglob
  7 MESSAGES=( $MAILDROP/*.eml )
  8 eval &quot;$NG&quot;
  9 
 10 #
 11 # Exit if there&#39;s nothing to do or report what&#39;s there
 12 #
 13 if [[ ${#MESSAGES[@]} -gt 0 ]]; then
 14     echo &quot;Files in the spool area:&quot;
 15     printf &quot;%s\n&quot; &quot;${MESSAGES[@]}&quot;
 16 else
 17     echo &quot;The spool area is empty&quot;
 18     exit
 19 fi</code></pre>
<p>The variable '<code>NG</code>' holds the state of '<code>nullglob</code>' before the script modifies it. Remember that '<code>shopt -p</code>' returns a list of commands that will revert the named options to their current state.</p>
<p>Next (line 6) the '<code>nullglob</code>' option is enabled.</p>
<p>The array '<code>MESSAGES</code>' is created on line 7 to hold the list of mail files found in the spool area. This is done with a pattern which matches files that end with the string '<code>.eml</code>'. If we didn't have '<code>nullglob</code>' enabled then when there were no files the array would contain the pattern - which would be misleading.</p>
<p>Having collected the file details '<code>nullglob</code>' is turned off by executing the command in the variable '<code>NG</code>' on line 8.</p>
<p>You might think that the script could just turn '<code>nullglob</code>' on then turn it off again when it's no longer needed. However, I prefer to use the technique I have shown here because it needs to have no knowledge of the state of the option before it's set, and restores that state afterwards.</p>
<p>By line 13 the array '<code>MESSAGES</code>' either contains a list of files or is empty. The script checks for these two cases by determining how many elements are in the array. Greater than zero means we have files to process and they are listed in lines 14 and 15. The script then goes on to do various things with the files.</p>
<p>If there were no files then the script reports this and exits.</p>
<p>That's it! This is not the only way to do this, but I like to write scripts that call as few sub-processes as I can, and this way appeals for that reason.</p>
<h2 id="links">Links</h2>
<ul>
<li>HPR show 1648 <a href="https://hackerpublicradio.org/eps.php?id=1648"><em>Bash parameter manipulation</em></a> looks at variables and arrays in Bash</li>
<li>HPR show 2278 <a href="https://hackerpublicradio.org/eps.php?id=2278"><em>Some supplementary Bash tips</em></a> introduces '<code>shopt</code>' and '<code>nullglob</code>'.</li>
</ul>
