1

Given the code below, how do I set a variable that I can use to call the 7z executable? The env:Path approach at the top works once but then the terminal must be reloaded or the command cannot be found. Powershell seems to be treating it as a string, not as an executable call. Ultimately, I need to be able to pull this value in from the environment.

# $env:Path += "C:\Program Files\7-Zip"
# works once, then the terminal must be reloaded

$7zip = "C:\Program Files\7-Zip\7z.exe"
$dirAsStr = "C:\Program Files\7-Zip\7z.exe"
$dirAsDir = Get-Item $dirAsStr

$extract_files = "somewhere"
$output = "someplace"

# $dirAsDir a -t7z $output\format_files.7z $extract_files\format.*
# ParserError: Unexpected token 'a' in expression or statement.
# $7zip a -t7z $output\format_files.7z $extract_files\format.*
# ParserError: Unexpected token 'a' in expression or statement.

C:\"Program Files"\7-Zip\7z.exe a -t7z $output\format_files.7z $extract_files\format.*
# works fine
2
  • 2
    Look like you need an ampersand in front of the variable. stackoverflow.com/a/72802405 Commented Sep 19, 2023 at 15:38
  • Wow, neat. Did not know about &. Thanks! Commented Sep 19, 2023 at 15:46

2 Answers 2

3

$env:Path += "C:\Program Files\7-Zip"

should be $env:Path += ";C:\Program Files\7-Zip" (note the ;) and it is effective for the remainder of the current session (process) only.

That is, you can then invoke 7-Zip as 7z ... in the same session.

If you want this modification to persist, i.e. to be available in all future sessions:

  • Either: Place the command in your $PROFILE file.

  • Or: Modify the persistent definition of the Path environment variable in the registry, e.g. interactively via sysdm.cpl

    • Note: Robustly updating Path programmatically is nontrivial, unfortunately - see this answer.

$7zip a -t7z...

In order to execute commands whose names or paths are stored in variables, you must invoke them via &, the call operator (which is a syntactic necessity in PowerShell):

& $7zip a -t7z ...

The same goes for command names or paths that are quoted as a whole:

  • C:\"Program Files"\7-Zip\7z.exe happens to work without &, because the argument starts with an unquoted string.

    • A an aside: Starting with a quoted string and appending an unquoted one is fundamentally unsupported in PowerShell; e.g.,
      & "C:\Program Files\"7-Zip\7z.exe wouldn't work, because the 7-Zip\7z.exe part would become a separate argument - see this answer.
  • By contrast, "C:\Program Files"\7-Zip\7z.exe" would require &

By contrast, use of & is optional with verbatim, unquoted command names and paths (e.g, 7z, C:\tools\7z.exe)

See this answer for details.

Sign up to request clarification or add additional context in comments.

2 Comments

Would this be a good idea or overkill? "$([IO.Path]::PathSeparator)$Env:ProgramFiles$([IO.Path]::DirectorySeparatorChar)7-Zip"
@lit, I'd say it's overkill, given not only that you're by definition running on Windows with a path like that, but also because PowerShell accepts \ and / interchangeably in provider paths. Thus, $Env:ProgramFiles\7-Zip should do (or (Join-Path $Env:ProgramFiles 7-Zip))
0

Please try this:

Invoke-Expression "& `"$7zip`" a -t7z $output\format_files.7z $extract_files\format.*"

2 Comments

To spell it out: Use of Invoke-Expression is rarely justified, but here it serves no purpose and needlessly complicates the solution. &, the call operator, is the only thing needed: & $7zip a -t7z $output\format_files.7z $extract_files\format.*

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.