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.*

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.