0

My first excursion into a real app in Powershell; I could write the code in a traditional .Net language, but I think Powershell is ideal for console apps like this. I've searched StackOverflow and found the (nearly) exact script I need; my issue is that I want to take a folder of files (on server fsA) and create 7-Zip archives on fsB named by the file date. For instance, all the files that were last written on 7/21/12 would be found in archive 20120721.7z. I'm basing this on the solution found here: Create a 7z Archive for files created by date using Powershell

Here is what I have so far:

$prog_dir = "C:\Progra~1\7-Zip\7z.exe"
$archive_dir = "\\fsa\Backup"
$input_dir = "\\fsb\Xml\Archive\"
$7zOpts = "-m0=PPMd:o32:mem192M"
$groups = dir $input_dir | group-object -property {$_.LastWriteTime.Date}
$groups | foreach{$cmd = $prog_dir + " a " + $archive_dir + "\$((Get-Date $_.Name).ToString(`"yyyyMMdd`")).7z $([string]::join(`" `", $_.Group)) " + $7zOpts} #; invoke-expression $cmd}
#
#Where to put this: "+ $input_dir +"???
#
$cmd

I can't seem to find a way to specify the input directory in the foreach line; I can put it at the beginning of the join statement, but it only adds the input directory to the first file in the list. For instance:

$groups | foreach{$cmd = $prog_dir + " a " + $archive_dir + "\$((Get-Date $_.Name).ToString(`"yyyyMMdd`")).7z " + $input_dir + "$([string]::join(`" `", $_.Group)) " + $7zOpts} #; invoke-expression $cmd}

produces the output

C:\Progra~1\7-Zip\7z.exe a \\fsa\Backup\20120722.7z \\fsb\Xml\Archive\255IQR.xml 2573WV.xml 257RMC.xml

where the last two files do not have the full path prepended? What am I doing wrong?

Community
  • 1
  • 1
Paul Sligar
  • 3
  • 1
  • 2
  • This isn't an answer to your current problem, but some advice: whenever I want to compress or decompress stuff with PowerShell I use 7zip via SevenZipSharp. I'd spend time implementing that instead of trying to get this command line to behave how you want it to. If you want some help on how to do that let me know and I can either point you to some documentation or write something up. – Chris N Jul 24 '12 at 14:50
  • @chris-n: I'd seen something about that; perhaps that's a better way to go. I'll look into it. In the meantime, anything you can point me to would be much appreciated. – Paul Sligar Jul 24 '12 at 14:55

1 Answers1

1

PowerShell is a shell, so running commands is pretty much the thing it should do well. So generally, if you resort to Invoke-Expression when running commands you're doing something very wrong. Let's try a different way:

$prog_dir = 'C:\Progra~1\7-Zip\7z.exe' # you don't need 8.3 names here, by the way
$archive_dir = '\\fsa\Backup'
$input_dir = '\\fsb\Xml\Archive\'
$7zOpts = '-m0=PPMd:o32:mem192M'
$groups = dir $input_dir | group-object -property {$_.LastWriteTime.Date}
$groups | foreach {
    $files = $_.Group | select -expand FullName
    $date = (Get-Date $_.Name).ToString('yyyyMMdd')
    & $prog_dir a $archive_dir\$date.7z $files $7zOpts
}
Joey
  • 344,408
  • 85
  • 689
  • 683
  • I appreciate the quick response; however, a couple of issues. Execution throws an error: Get-Date : Cannot bind parameter 'Date' to the target. Exception setting "Date": "Object reference not set to an i nstance of an object." And it compresses all files into one archive. If there are files with different dates, the intent was for them to be in different archives named according to the date. – Paul Sligar Jul 24 '12 at 12:52
  • This was meant to replace the contents of your `ForEach-Object` scriptblock. The one where you create `$cmd` and `iex` it. – Joey Jul 24 '12 at 12:55
  • I apologize for being so dense; so the line becomes $groups | foreach{$files = $_.Group | %{ $input_dir + $_ };& $prog_dir a $archive_dir\$((Get-Date $_.Name).ToString('yyyyMMdd')).7z $files $7zOpts} ? – Paul Sligar Jul 24 '12 at 14:50
  • That was the intention, yes. I edited the answer with a complete script and also revised a few parts (e.g. using the FullName property instead of concatenating a path and file name). – Joey Jul 24 '12 at 15:07