2

I have the following, perfectly working ps1 script:

function Get-ScriptDirectory {
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}

$currentDir = Get-ScriptDirectory

node $currentDir/yarn.js $args

I would like to eliminate the $currentDir variable. I am trying to run:

function Get-ScriptDirectory {
    $Invocation = (Get-Variable MyInvocation -Scope 1).Value
    Split-Path $Invocation.MyCommand.Path
}

node (Get-ScriptDirectory)/yarn.js $args

But this fails - it looks like Get-ScriptDirectory output becomes the first argument. I've tried using quotes, and that doesn't work either - the brackets no longer expand.

How do I run a command using the output of a function?

mikemaccana
  • 110,530
  • 99
  • 389
  • 494
  • @PetSerAl Thanks! Whats the difference between `$()` and `()` anyway? Add it as an answer and I'll mark it correct. – mikemaccana Jul 12 '18 at 09:40
  • Blog that explains [using subexpressions within strings](https://www.pdq.com/blog/using-subexpressions-within-strings/) :) – henrycarteruk Jul 12 '18 at 09:48

1 Answers1

2

Based on past experience, there's no point in waiting for PetSerAl to post an answer, though his pointers are always appreciated.

Your options are:

  • Either: Use an expression to construct the path:

    node  ((Get-ScriptDirectory) + '/yarn.js') $Args
    
  • Or: Use an expandable string (string interpolation):

    node  "$(Get-ScriptDirectory)/yarn.js" $Args
    

Background:

  • (...) is required to enclose a single expression or command in a context where a command argument or subexpression is expected (which could be a command invocation that itself needs to be wrapped in (...) or an embedded expression whose evaluation precedence needed clarification).

  • $(...)is the - more flexible, but slower - subexpression operator:

    • In order to embed an expression or command(s) in an expandable string ("..."), you must use $(...) - (...) wont' work.

    • Outside of an expandable string, while $(...) generally also works, there's generally no need to use it, unless you need to execute multiple statements.

      • For a single expression / command, (...) is not only sufficient but performs better.

Additional information:

  • To learn about PowerShell's fundamental parsing modes, see Get-Help about_Parsing

  • To learn about PowerShell's string expansion (string interpolation) rules, see this answer of mine.

  • For a comprehensive discussion of how unquoted command-line tokens are parsed in argument mode (as command arguments), see this answer of mine.

mklement0
  • 382,024
  • 64
  • 607
  • 775