title: Bash: can't call a function; No such file or directory
body: <p>I am having huge issues that have blocked me all day.</p>
  
  <p>I have a number of functions files with various functions based on use, ie. SSH, logging etc.</p>
  
  <p>I have a script that runs where I add errors to an error array which is global. I have an error trap that calls a script in another 'exit_functions' file.</p>
  
  <p>In this exit_functions file I do various things, but the part I am having issues with is a loop that runs of this array and pulls out the array elements which are actually commands. These commands are <strong>functions</strong> within one of the functions files that have been included in the calling script using the normal . /path/to/functions_file syntax.</p>
  
  <p>All my other functions such as logging etc are working out of the exit_functions file, it is just these particular functions that can't be called. I get an error:</p>
  
  <pre><code>/functions/exit_functions: line 109: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory
  </code></pre>
  
  <p>Now, killSSHTunnel is a function that sits in a functions file that has been included previously just as other functions files have been included. I only get this error using these functions calls out of an array.</p>
  
  <p>I am not sure if I have described it properly - please let me know if I can provide any other info.</p>
  
  <hr>
  
  <p><strong>EDIT full function code below:</strong></p>
  
  <p><strong>/functions/exit_functions file:</strong>
      exitTrap (){
          local LCL_SCRIPT_ERROR</p>
  
  <pre><code>    if [ $ERR_COUNT_EXIT_FUNCT -gt 0 ]; then
          for LCL_SCRIPT_ERROR in "${ERROR_ARRAY[@]}"; do
              case $LCL_SCRIPT_ERROR in
                  SVN_IMPORT      )   # match the SVN_IMPORT error name and search for specific commands to run
                                      exitMsg "$LCL_SCRIPT_ERROR; 111"
                                      executeErrorActions $LCL_SCRIPT_ERROR
  
                                      exitScript 111
                                      ;;
  
                  *               )   exitMsg "$LCL_SCRIPT_ERROR; 255"
                                      exitScript 255
                                      ;;
              esac
          done
      fi
  }
  </code></pre>
  
  <p>So my test code introduces an error state that ends up calling the function above (exitTrap). It has already populated an array named ERROR_ARRAY.</p>
  
  <p>So the executeErrorActions function, also in /functions/exit_functions, loops over the associative array, ERROR_ACTION_ARRAY, looking for a key named (in this test) <strong>SVN_IMPORT</strong>. When it finds this key it is looking for a string that is ':' delimited. Each delimited section will be a separate command that I was to run when this error condition arises. In my test I have a <strong>single</strong> entry (no delimiters) that is simply: *closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck*</p>
  
  <p>Now, with the function below it works fine when I <strong>do not</strong> include the section between IFS= and unset IFS and instead just use the single line that has the double comments hashes below. As soon as I introduce the IFS separator to break the string up I get the error:</p>
  
  <blockquote>
    <p>/functions/exit_functions: line 109: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory</p>
  </blockquote>
  
  <pre><code>executeErrorActions (){
      if [ ! $# -eq 1 ]; then
          return 1
      fi
  
      local ERROR_NAME=$1
      local ERROR_ACTION
  
      #ERROR_KEY="SVN_IMPORT"
  
      for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do
          #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]}
          if [ $ERROR_NAME == $ERROR_ACTION ]; then
  
              ##$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]})
  
              IFS=":"
              for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do
                  $i
              done
              unset IFS
              return 0
          fi
      done
  }
  </code></pre>
  
  <p>Here is the set -x output of the test run using two ':' delimitered commands, the same <em>closeSSHTunnel</em> function above and a simple <em>ls -la</em> call. I add these to the ERROR_ACTION_ARRAY using the addError function call as below:</p>
  
  <pre><code>addError SVN_IMPORT closeSSHTunnel $SSH_TUNNEL_LCK_FILE:ls -la
  </code></pre>
  
  <p>This is the set -x output:</p>
  
  <pre><code>+ executeErrorActions SVN_IMPORT
  + '[' '!' 1 -eq 1 ']'
  + local ERROR_NAME=SVN_IMPORT
  + local ERROR_ACTION
  + for ERROR_ACTION in '${!ERROR_ACTION_ARRAY[@]}'
  + '[' SVN_IMPORT == SVN_IMPORT ']'
  + IFS=:
  + for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}'
  + 'closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck'
  /functions/exit_functions: line 116: closeSSHTunnel /tmp/ssh_tunnel_iA0yj.lck: No such file or directory
  + for i in '${ERROR_ACTION_ARRAY[$ERROR_ACTION]}'
  + 'ls -la'
  /functions/exit_functions: line 116: ls -la: command not found
  + unset IFS
  + return 0
  </code></pre>
  
  <p><strong>Note how one of them says 'No such file or directory and the other says 'command not found'. This is now day 2 trying to sort this out !</strong></p>
  
  <p><em><strong>My conclusion is that the IFS change and the string breakup is causing issues.</em></strong></p>
  
  <p><strong>EDIT 2</strong></p>
  
  <p>If I move the IFS calls around a bit and terminate the IFS on the ':' char inside the loop and then establish it again after the execute call it all works !!!!!!</p>
  
  <pre><code>for ERROR_ACTION in ${!ERROR_ACTION_ARRAY[@]}; do
          #echo KEY: $i VALUE: ${ERROR_ACTION_ARRAY[$i]}
          if [ $ERROR_NAME == $ERROR_ACTION ]; then
              #$(${ERROR_ACTION_ARRAY[$ERROR_ACTION]})
              IFS=$':'
              for i in ${ERROR_ACTION_ARRAY[$ERROR_ACTION]}; do
                  unset IFS
                  $i
                  IFS=$':'
              done
              unset IFS
              return 0
          fi
  done
  </code></pre>
  
  <p>Can anyone explain this ?</p>