Reputation: 5916
Consider the following command:
7z.exe a -t7z folder.7z folder
I have the following two stripped down powershell scripts
File 1: common.ps1
function Archive-Folder ($src, $dest_path, $archive_name) {
$script_dir = split-path $script:MyInvocation.MyCommand.Path
if ((test-path $src) -eq $false) {
write-error "$src is not a valid source directory"
#return
return $false
}
if ((test-path $dest_path) -eq $false) {
write-error "$dest_path is not a valid destination directory"
#return
return $false
}
if ([string]::IsNullOrWhiteSpace($archive_name) -eq $true) {
write-error "$archive_name is not a valid archive name"
#return
return $false
}
write-verbose "archiving the folder"
$archive_command = "$script_dir\7z.exe a -t7z $dest_path\$archive_name $src"
$exe = "$script_dir\7z.exe"
$arguments = @('a', '-t7z', "$dest_path\$archive_name", "$src")
iex $archive_command
# this doesn't stream the output. it prints it all at once.
# & $exe $arguments | write-verbose
return $true
}
File 2: script.ps1
$script_dir = split-path $script:MyInvocation.MyCommand.Path
. "$script_dir\common.ps1"
$VerbosePreference = "Continue"
$src = 'C:\some\source'
$backup_path = 'C:\some\destination'
$date_format = 'yyyy_MM_dd_HHmm'
$date = get-date
$date_str = $date.tostring($date_format)
$date_ticks = $date.ticks
$archive_name = "backup-$date_str-$date_ticks.7z"
# this prints the output streamed. The output ends with `True`
archive-folder $src $backup_path $archive_name
# the following however doesn't output anything. in order to separate the command output from my function output,
# i was printing the command output using write-verbose
$isSuccess = archive-folder $src $backup_path $archive_name
if ($isSuccess -eq $true) {
#proceed with the rest of the code
}
With inputs from @Christian & @zdan, I was able to isolate the issue to the capturing of the return value. Similar to archive-folder
, I have other functions that execute some commandline tool. I was thinking that each of these functions can return a true or false depending on whether the function was called with the right operations and the commandline tool executed properly.
However, if I capture the return value of my archive-folder
function, then the output of the command doesn't get printed to the console. Also, my return value doesn't consist of a true or false value. It consists of the entire output of the command.
My first attempt at solving this was to write the command execution statement as iex $archive_command | write-verbose
, but this did not stream the output.
I suppose I can check for side effects the commandline tool has in case of success (like presence of the archive file) to determine whether my function executed successfully, but am not sure if I will be able to do this for all functions that I may end up creating.
Is there a way to return a value and also stream the output of a commandline tool?
EDIT 2
With regards to why am I diving the code into two separate files/functions, my actual use scenario is as follows
The
script.ps1
will be coordinating this flow. Backup the database (mongodb generates files for each collection of the db). Archive the database backup. Upload the archive to S3. Each of these steps will be done by a separate function incommon.ps1
. Thescript.ps1
will only contain the glue code. Posting all this might have complicated the question and I felt wasn't needed to understand the issue am facing
EDIT 1
If the folder being compressed has 5 files, 7zip will first output the copyright. Then it will output the text Scanning
. Then it will output a line Creating archive at some location
. Then it will process each file, outputting the progress for each file, one by one. This way, we get constant feedback about the progress of the operation.
If I execute the powershell function, then I see no output for the duration of the operation and then all the output at once. I get no feedback from 7zip. I would like to simulate the behaviour that 7zip shows when ran as a standalone exe.
Upvotes: 1
Views: 5411
Reputation: 3626
This works for me:
& 7z.exe a -t7z -bsp1 $archive_name $src 2>&1 | Out-Host
The -bsp1
switch redirects the progress information
stream to the stdout
stream. This is a feature of 7z. Also look at the -bb
switch.
The 2>&1
redirects the error stream to stdout
. This is a feature of PowerShell.
-bs (Set output stream for output/error/progress line) switch Syntax
Syntax
-bs{o|e|p}{0|1|2}
{id} | Stream Type ................................ o | standard output messages e | error messages p | progress information{N} | Stream Destination ................................ 0 | disable stream 1 | redirect to stdout stream 2 | redirect to stderr stream
Upvotes: 6
Reputation: 60976
why not this way? If you need
function archive-folder ($src, $archive_name) {
$origcolor = [console]::ForegroundColor
[console]::ForegroundColor = "yellow"
"archiving $src"
$command = "7z.exe a -t7z $archive_name $src"
iex $command
[console]::ForegroundColor = $origcolor
}
My trivial caller function:
Function k
{
dir c:\ps\ita
Write-Host "Starting 7zippping from K function"
archive-folder -archive_name c:\ps\pippo.7z c:\ps\ita
Write-Host "7zipping from function k ended"
}
and what I see in powershell console ( in yellow the output from archive-folder
)
k
Directory: C:\ps\ita
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a--- 08/06/2011 19:26 5,502 MB ita.txt
-a--- 28/05/1994 16:59 165,624 KB ITALIANO.A
-a--- 28/05/1994 16:54 53,903 KB ITALIANO.B
-a--- 28/05/1994 17:00 165,541 KB ITALIANO.C
-a--- 08/06/2011 11:06 98,609 KB ITALIANO.D
-a--- 28/05/1994 17:00 72,077 KB ITALIANO.E
-a--- 28/05/1994 16:54 80,813 KB ITALIANO.F
-a--- 28/05/1994 16:55 78,312 KB ITALIANO.G
-a--- 28/05/1994 16:55 2,412 KB ITALIANO.H
-a--- 08/06/2011 11:07 298,609 KB ITALIANO.I
-a--- 28/05/1994 16:55 1,033 KB ITALIANO.J
-a--- 28/05/1994 16:55 1,777 KB ITALIANO.K
-a--- 28/05/1994 17:01 71,553 KB ITALIANO.L
-a--- 08/06/2011 10:59 162,084 KB ITALIANO.M
-a--- 28/05/1994 16:56 47,123 KB ITALIANO.N
-a--- 28/05/1994 16:56 72,973 KB ITALIANO.O
-a--- 08/06/2011 19:37 264,109 KB ITALIANO.P
-a--- 28/05/1994 16:56 10,512 KB ITALIANO.Q
-a--- 08/06/2011 19:38 327,348 KB ITALIANO.R
-a--- 08/06/2011 19:40 566,512 KB ITALIANO.S
-a--- 08/06/2011 10:57 184,719 KB ITALIANO.T
-a--- 28/05/1994 16:57 19,378 KB ITALIANO.U
-a--- 28/05/1994 16:57 61,552 KB ITALIANO.V
-a--- 28/05/1994 16:57 1,334 KB ITALIANO.W
-a--- 28/05/1994 16:57 1,368 KB ITALIANO.X
-a--- 28/05/1994 16:57 533 B ITALIANO.Y
-a--- 28/05/1994 17:01 7,054 KB ITALIANO.Z
Starting 7zippping from K funztion
archiving c:\ps\ita
7-Zip 4.65 Copyright (c) 1999-2009 Igor Pavlov 2009-02-03
Scanning
Updating archive c:\ps\pippo.7z
Compressing ITA\ITALIANO.H
Compressing ITA\ITALIANO.C
Compressing ITA\ITALIANO.F
Compressing ITA\ita.txt
Compressing ITA\ITALIANO.O
Compressing ITA\ITALIANO.A
Compressing ITA\ITALIANO.B
Compressing ITA\ITALIANO.D
Compressing ITA\ITALIANO.E
Compressing ITA\ITALIANO.G
Compressing ITA\ITALIANO.I
Compressing ITA\ITALIANO.J
Compressing ITA\ITALIANO.K
Compressing ITA\ITALIANO.L
Compressing ITA\ITALIANO.M
Compressing ITA\ITALIANO.N
Compressing ITA\ITALIANO.P
Compressing ITA\ITALIANO.Q
Compressing ITA\ITALIANO.R
Compressing ITA\ITALIANO.S
Compressing ITA\ITALIANO.T
Compressing ITA\ITALIANO.U
Compressing ITA\ITALIANO.V
Compressing ITA\ITALIANO.W
Compressing ITA\ITALIANO.X
Compressing ITA\ITALIANO.Y
Compressing ITA\ITALIANO.Z
Everything is Ok
7zipping from function k ended
Upvotes: 0
Reputation: 29470
It seems to me that you should be able to just do:
&7z.exe a -t7z $archive_name $src | write-verbose
Unless there is something I am missing.
Upvotes: 0