title: How can one avoid expansion errors in functions killing the shell?
body: <p>I ran into a surprising behavior in one of my shell scripts today.  It is demonstrated by the following example:</p>
  
  <p><strong>test.sh</strong></p>
  
  <pre><code>#!/bin/bash
  
  do_it() {
    shopt -s failglob
    {
      rm killme.*
      echo "and then ..."
    } 2&gt;/dev/null || echo "glob error"
  
    echo "life goes on ..."
  }
  
  do_it || echo "function failed"
  </code></pre>
  
  <p>The idea in the original script was that I wanted to allow glob expansion errors to occur for a particular command so as to avoid executing that one command when there were no arguments, yet <em>detect</em> that error and take alternative action.  My expectation was that when <code>killme.*</code> did not match anything, executing the above script via</p>
  
  <pre><code>./test.sh || echo "script failed"
  </code></pre>
  
  <p>would emit</p>
  
  <pre><code>glob error
  life goes on ...
  </code></pre>
  
  <p>or maybe</p>
  
  <pre><code>function failed
  </code></pre>
  
  <p>.  It didn't (with Bash 4.2.46).  Instead it printed</p>
  
  <pre><code>script failed
  </code></pre>
  
  <p>.  While troubleshooting the issue, I discovered something even more curious: if I simplify the script further by eliminating the function, the behavior changes.  That is, consider this alternative script:</p>
  
  <p><strong>test2.sh</strong></p>
  
  <pre><code>#!/bin/bash
  
  shopt -s failglob
  
  {
    rm killme.*
    echo "and then ..."
  } 2&gt;/dev/null || echo "glob error"
  
  echo "life goes on ..."
  </code></pre>
  
  <p>If I run <em>that</em> via</p>
  
  <pre><code>./test2.sh || echo "script failed"
  </code></pre>
  
  <p>, it prints</p>
  
  <pre><code>life goes on ...
  </code></pre>
  
  <p>There seem to be some other weird variations when a function like the one in the first script is called in a loop, but I haven't fully characterized that.</p>
  
  <p><strong>Questions</strong>:</p>
  
  <ol>
  <li><p>Is this documented behavior?  My examination of the Bash manual has been unavailing.  It specifies that an "expansion error" occurs, and it seems natural that that's a <em>shell</em> error, not an error in the command, but if there's anything by which I should be able to predict the details of the observed results then I've missed it.  </p></li>
  <li><p>I can solve the issue by running the expansion in a subshell, but is there any lighter weight workaround?  I guess I could perform the expansion in advance, with <code>failglob</code> unset, and test the result, but that's messy and contains a race condition.</p></li>
  </ol>