title: Using nested command substitution in jenkins pipeline sh step
body: <p>I'm trying to flatten a results directory prior to archiving using a symbolic link to the relevant inner folder that first traverses a bunch of variable path names determined at runtime. I can't quite seem to get the syntax right with this command substitution approach I picked up from this SO <a href="https://stackoverflow.com/a/12864729/1330381">answer</a>.</p>
  
  <p>Question: is there a rule for how to properly escape command substitution chains from a Jenkins pipeline step that I'm unaware of?</p>
  
  <p><strong>Pipeline Script snippet</strong></p>
  
  <pre><code>post {
    always {   
      sh """
      echo 'Link to inner output result folder to make the artifacts more shallow'
      echo ln -sf dirname find $output_dir -name $jUnitResult $WORKSPACE/$output_dir_inner
      ln -sf $(dirname $(find ${output_dir} -name ${jUnitResult})) $WORKSPACE/$output_dir_inner
      """
  
      archiveArtifacts output_dir_inner
    }
  }
  </code></pre>
  
  <p><strong>Console Output</strong></p>
  
  <pre><code>org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  WorkflowScript: 52: illegal string body character after dollar sign;
     solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}" @ line 52, column 21.
                 ln -sf $(dirname $(find ${output_dir} -name ${jUnitResult})) $WORKSPACE/$output_dir_inner
                         ^
  
  1 error
  
      at org.codehaus.groovy.control.ErrorCollector.failIfErrors(ErrorCollector.java:310)
      at org.codehaus.groovy.control.ErrorCollector.addFatalError(ErrorCollector.java:150)
      at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:120)
      at org.codehaus.groovy.control.ErrorCollector.addError(ErrorCollector.java:132)
      at org.codehaus.groovy.control.SourceUnit.addError(SourceUnit.java:350)
      at org.codehaus.groovy.antlr.AntlrParserPlugin.transformCSTIntoAST(AntlrParserPlugin.java:139)
      at org.codehaus.groovy.antlr.AntlrParserPlugin.parseCST(AntlrParserPlugin.java:110)
      at org.codehaus.groovy.control.SourceUnit.parse(SourceUnit.java:234)
      at org.codehaus.groovy.control.CompilationUnit$1.call(CompilationUnit.java:168)
      at org.codehaus.groovy.control.CompilationUnit.applyToSourceUnits(CompilationUnit.java:943)
      at org.codehaus.groovy.control.CompilationUnit.doPhaseOperation(CompilationUnit.java:605)
      at org.codehaus.groovy.control.CompilationUnit.processPhaseOperations(CompilationUnit.java:581)
      at org.codehaus.groovy.control.CompilationUnit.compile(CompilationUnit.java:558)
      at groovy.lang.GroovyClassLoader.doParseClass(GroovyClassLoader.java:298)
      at groovy.lang.GroovyClassLoader.parseClass(GroovyClassLoader.java:268)
      at groovy.lang.GroovyShell.parseClass(GroovyShell.java:688)
      at groovy.lang.GroovyShell.parse(GroovyShell.java:700)
      at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.doParse(CpsGroovyShell.java:131)
      at org.jenkinsci.plugins.workflow.cps.CpsGroovyShell.reparse(CpsGroovyShell.java:125)
      at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.parseScript(CpsFlowExecution.java:560)
      at org.jenkinsci.plugins.workflow.cps.CpsFlowExecution.start(CpsFlowExecution.java:521)
      at org.jenkinsci.plugins.workflow.job.WorkflowRun.run(WorkflowRun.java:330)
      at hudson.model.ResourceController.execute(ResourceController.java:97)
      at hudson.model.Executor.run(Executor.java:429)
  Finished: FAILURE
  </code></pre>
  
  <p>I see a similar failure when attempting</p>
  
  <p><strong>Pipeline Script snippet</strong></p>
  
  <pre><code>ln -sf $(dirname $(find $output_dir -name $jUnitResult)) $WORKSPACE/$output_dir_inner
  </code></pre>
  
  <p><strong>Console Output</strong></p>
  
  <pre><code>org.codehaus.groovy.control.MultipleCompilationErrorsException: startup failed:
  WorkflowScript: 49: illegal string body character after dollar sign;
     solution: either escape a literal dollar sign "\$5" or bracket the value expression "${5}" @ line 49, column 13.
                 sh """
                 ^
  </code></pre>