I can't seem to solve this, been struggling with it for a while (maybe it's simple; I just can't see it as I've been looking at it for so long). I can get the 7z.exe syntax to work, but when I try and put it together into a simple script, it fails.
e.g., if I run .\zip.ps1 "C:\test\test.zip" "C:\test\test1.txt" "C:\test\test2.txt*
Instead of zipping up the 2 files required, it zips up everything in the C:\test folder, completely ignoring my arguments.
How can I adjust the below string syntax so that 7z.exe will correctly respect the input arguments and compress them from within a PowerShell script?
"Received $($args.Count) files:"
$parent = Split-Path (Split-Path $args[0]) -Leaf
$sevenzip = "C:\Program Files\7-Zip\7z.exe"
$zipname = "$($parent) $(Get-Date -Format 'yyyy_MM_dd HH_mm_ss').zip"
$args_line = $args | foreach-object { "`"$_`"" }
# $args_line = '"' + $($args -join """ """) + '"' # Want to use """ here so that it can capture not only files with spaces, but files with ' in the filename
''
"Zip Name : $zipname"
''
"Arguments : $args_line"
''
if (Test-Path $sevenzip) {
if (Test-Path "C:\0\$zipname") { rm "C:\0\$zipname" -Force }
''
'String output of the line to run:'
"& ""$sevenzip"" a -r -tzip ""C:\0\$zipname"" $args_line" # Taking this output and pasting onto console works.
''
& "$sevenzip" a -r -tzip "C:\0\$zipname" "$args_line" # This does not work
} else {
"7z.exe was not found at '$sevenzip', please check and try again"
}
The error that I get is:
Files read from disk: 0
Archive size: 22 bytes (1 KiB)
Scan WARNINGS for files and folders:
1 : The system cannot find the file specified.
----------------
Pass
$argsdirectly to your& "$sevenzip"call:This makes PowerShell pass the array elements as individual arguments, automatically enclosing them in
"..."if needed (based on whether they contain spaces).Using arrays as arguments for external programs is in effect an implicit form of array-based splatting; thus, you could alternatively pass
@args.Generally, note that in direct invocation[1] you cannot pass multiple arguments to an external program via a single string; that is, something like
"$args_line"cannot be expected to work, because it is passed as a single argument to the target program.If you want to emulate the resulting part of the command line, for display purposes:
Note:
"..."- namely based on whether it contains at least one space - and the resulting tokens are joined to form a single, space-separated list (string)."chars.A simplified example:
Output:
Note:
Write-Outputis used in lieu of an external program for convenience. Technically, you'd have to use@argsinstead of$argsin order to pass the array elements as individual, positional arguments, but, as stated, this is the default behavior with externals programs.Write-Output, as a PowerShell-native command, receives the array as a whole, as a single argument when$argsis used; it just so happens to process that array the same way as if its elements had been passed as individual arguments.[1] You can use a single string as an
-ArgumentListvalue forStart-Process. However,Start-Processis usually the wrong tool for invoking console applications such as7z.exe- see this answer.