synetron
asked on
Tweak an unzip script
When i run:
This works flawlessly.
I need however to arrange the destination directory to receive the extracted files in a unique sub-directory.
Ideally i would arranged them based on characters 5 through 12 of the original zip file name, if however i can only use the original zip file name without the .zip extention as the name of my directory i would consider it a success.
For any verterans out there looking to help me out i obviously get a
as for any rookies like myself, this isn't the solution... :-(
also, should I
Move-Item $_ "C:\script\test\ftp\archiv e" within my foreach-object{
} to make it cleaner or just wait until all have completed before moving all such items to the archive? and can I Move-Item $_ within the foreach statement?
Thanks
function Extract-Zip
{
param([string]$zipfilename, [string] $destination)
if(test-path($zipfilename))
{
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$destinationFolder = $shellApplication.NameSpace($destination)
$destinationFolder.CopyHere($zipPackage.Items())
}
}
#find all MAC files in the immediate directory
dir "C:\script\test\ftp\MAC*.zip" | foreach-object{
extract-zip $_ c:\script\test\Master\MAC
extract-zip $_ c:\script\test\Working\MAC
}
Move-Item "C:\script\test\ftp\MAC*" "C:\script\test\ftp\archive"
#find all MAH files in the immediate directory
dir "C:\script\test\ftp\MAH*.zip" | foreach-object{
extract-zip $_ c:\script\test\Master\MAH\
extract-zip $_ c:\script\test\Working\MAH\
}
Move-Item "C:\script\test\ftp\MAH*" "C:\script\test\ftp\archive"
#find all MAM files in the immediate directory
dir "C:\script\test\ftp\MAM*.zip" | foreach-object{
extract-zip $_ c:\script\test\Master\MAM
extract-zip $_ c:\script\test\Working\MAM
}
Move-Item "C:\script\test\ftp\MAM*" "C:\script\test\ftp\archive"
This works flawlessly.
I need however to arrange the destination directory to receive the extracted files in a unique sub-directory.
Ideally i would arranged them based on characters 5 through 12 of the original zip file name, if however i can only use the original zip file name without the .zip extention as the name of my directory i would consider it a success.
For any verterans out there looking to help me out i obviously get a
You cannot call a method on a null-valued expression.when i add "\$_" to the end of my extraction path.
At C:\script\test\unzip_archive1.ps1:10 char:30
+ $destinationFolder.CopyHere <<<< ($zipPackage.Items())
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
as for any rookies like myself, this isn't the solution... :-(
also, should I
Move-Item $_ "C:\script\test\ftp\archiv
} to make it cleaner or just wait until all have completed before moving all such items to the archive? and can I Move-Item $_ within the foreach statement?
Thanks
try add $_.BaseName to the end of my extraction path.
also on lines 18-19 you call the extract-zip with the same file but different destination.
i think u should simply copy the files to the other destination once the first call to extract-zip is done.
i think u should simply copy the files to the other destination once the first call to extract-zip is done.
ASKER
Thank you for the reply. I added $_.BaseName to the end of the extraction paths and it returned:
You cannot call a method on a null-valued expression.
At C:\script\test\test.ps1:10 char:30
+ $destinationFolder.CopyHer e <<<< ($zipPackage.Items())
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
As for lines 18-19 and moving to the other destination after the first extraction is complete, this doesn't fit the current need to archive for backup and have two working extracted copies ready for the following morning.
You cannot call a method on a null-valued expression.
At C:\script\test\test.ps1:10
+ $destinationFolder.CopyHer
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
As for lines 18-19 and moving to the other destination after the first extraction is complete, this doesn't fit the current need to archive for backup and have two working extracted copies ready for the following morning.
try create the destination folder before doing the actual unzipping inside the function.
function Extract-Zip
{
param([string]$zipfilename, [string] $destination)
if(test-path($zipfilename))
{ md $destination #creates destination folder
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$destinationFolder = $shellApplication.NameSpace($destination)
$destinationFolder.CopyHere($zipPackage.Items())
}
}
ASKER
Well that was interesting...
New-Item : The given path's format is not supported.
At line:38 char:24
+ $scriptCmd = {& <<<< $wrappedCmd -Type Directory @PSBoundParameters }
+ CategoryInfo : InvalidOperation: (C:\script\test\...py.zip. BaseName:S tring) [New-Item], NotSupportedExc
eption
+ FullyQualifiedErrorId : ItemExistsNotSupportedErro r,Microsof t.PowerShe ll.Command s.NewItemC ommand
You cannot call a method on a null-valued expression.
At C:\script\test\mema.ps1:11 char:30
+ $destinationFolder.CopyHer e <<<< ($zipPackage.Items())
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
New-Item : The given path's format is not supported.
At line:38 char:24
+ $scriptCmd = {& <<<< $wrappedCmd -Type Directory @PSBoundParameters }
+ CategoryInfo : InvalidOperation: (C:\script\test\...py.zip.
eption
+ FullyQualifiedErrorId : ItemExistsNotSupportedErro
You cannot call a method on a null-valued expression.
At C:\script\test\mema.ps1:11
+ $destinationFolder.CopyHer
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
ASKER
unless I'm mistaken, the inability to designate the destination lies in trying to use a variable (pardon the ignorance in accurate terms) like $_ or $_.BaseName in the extraction section (lines 18, 19, for example) since the extract-zip is a call to the function and thus the $_ which typically would reference the file being currently processed (by the for each section) has a null value as it's an argument being processed within the function...
If that is correct, then i should create the directory before i extract the data to it within the ForEach with something like "MD <PATH TO DIRECTORY>\$_.BaseName" but still have no way to call upon the name of the subdirectory i just created within my extract-zip function as this will be unique to each file being extracted.
Could this possibly be resolved by listing the currently processed file name as a string
$a = $_.BaseName
who's value can be accessed both in my for each statements and passed to the function? could a variable be set to represent this value... if so, how? could this type of statement be made before the function and stored (thinking object oriented here... ) outside of the function and outside of the ForEach sections thus being available to both or would the $_ only work when it's given life by the ForEach section of the script?
I can't help but feel I'm so close, but my limitation in experience (this is my first ever PS script) is killing me.
If that is correct, then i should create the directory before i extract the data to it within the ForEach with something like "MD <PATH TO DIRECTORY>\$_.BaseName" but still have no way to call upon the name of the subdirectory i just created within my extract-zip function as this will be unique to each file being extracted.
Could this possibly be resolved by listing the currently processed file name as a string
$a = $_.BaseName
who's value can be accessed both in my for each statements and passed to the function? could a variable be set to represent this value... if so, how? could this type of statement be made before the function and stored (thinking object oriented here... ) outside of the function and outside of the ForEach sections thus being available to both or would the $_ only work when it's given life by the ForEach section of the script?
I can't help but feel I'm so close, but my limitation in experience (this is my first ever PS script) is killing me.
i probably missing something here cause if the initial script is working, it should work if only thing is to change the destination folder based on the file name.
can u put write-host $destination inside the function?
also use test-path before creating the folder:
can u put write-host $destination inside the function?
also use test-path before creating the folder:
function Extract-Zip
{
param([string]$zipfilename, [string] $destination)
write-host $destination
if(test-path($zipfilename))
{
if((Test-Path $destination) -eq $False){
md $destination #creates destination folder
}
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$destinationFolder = $shellApplication.NameSpace($destination)
$destinationFolder.CopyHere($zipPackage.Items())
}
}
ASKER
Thank you sedgwick for your continued thoughts on the matter. I attempted this in various methods with no luck.
1. the destination directory does not create
2. the files still extract to the destination path without a unique sub-directory for each
mostly, this is what I'm seeing now:
1. the destination directory does not create
2. the files still extract to the destination path without a unique sub-directory for each
mostly, this is what I'm seeing now:
c:\script\test\Master\MAH\C:\script\ test\ftp\M AH.2012021 3-02.20.01 - Copy.zip
Test-Path : The given path's format is not supported.
At C:\script\test\mema.ps1:7 char:14
+ if((Test-Path <<<< $destination) -eq $False){
+ CategoryInfo : InvalidOperation: (C:\script\test\...0.01 - Copy.zip:String) [Test-Path], NotSupportedEx
ception
+ FullyQualifiedErrorId : ItemExistsNotSupportedError,Microsof t.PowerShe ll.Command s.TestPath Command
New-Item : The given path's format is not supported.
At line:38 char:24
+ $scriptCmd = {& <<<< $wrappedCmd -Type Directory @PSBoundParameters }
+ CategoryInfo : InvalidOperation: (C:\script\test\...0.01 - Copy.zip:String) [New-Item], NotSupportedExc
eption
+ FullyQualifiedErrorId : ItemExistsNotSupportedError,Microsof t.PowerShe ll.Command s.NewItemC ommand
You cannot call a method on a null-valued expression.
At C:\script\test\mema.ps1:13char:30
+ $destinationFolder.CopyHere <<<< ($zipPackage.Items())
+ CategoryInfo : InvalidOperation: (CopyHere:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
the concatenation of the $destination folder is wrong.
that's why u get:
c:\script\test\Master\MAH\ C:\script\ test\ftp\M AH.2012021 3-02.20.01 - Copy.zip
instead of:
c:\script\test\Master\MAH\ MAH.201202 13-02.20.0 1 - Copy.zip
please post the whole script again, i'll test it on my machine and make it work.
that's why u get:
c:\script\test\Master\MAH\
instead of:
c:\script\test\Master\MAH\
please post the whole script again, i'll test it on my machine and make it work.
ASKER
sedgwick, I can't thank you enough for your help, i believe I've had a breakthrough. I'll repost the script that I now have working...
you got me to thinking about the destination etc. so i started looking at some of the attempts early on in this project when i was trying to create the file structure then populate with 7zip command line interface... an attempt that failed miserably, and the light bulb went off.
function Extract-Zip
{
param([string]$zipfilename, [string] $destination)
if(test-path($zipfilename))
{
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$destinationFolder = $shellApplication.NameSpace($destination)
$destinationFolder.CopyHere($zipPackage.Items())
}
}
#find all MAC files in the immediate directory
dir "C:\script\test\ftp\MAC*.zip" | foreach-object{
#create directory
$id = $_.Name.SubString(4,8);
if(-not (Test-Path c:\script\test\Master\MAC\$id)) {mkdir c:\script\test\Master\MAC\$id};
#extract
extract-zip $_ c:\script\test\Master\MAC\$id
#create directory
if(-not (Test-Path c:\script\test\Working\MAC\$id)) {mkdir c:\script\test\Working\MAC\$id};
#extract
extract-zip $_ c:\script\test\Working\MAC\$id
}
#clean up to avoid duplicate work at next run
Move-Item "C:\script\test\ftp\MAC*" "C:\script\test\ftp\archive"
#find all MAH files in the immediate directory
dir "C:\script\test\ftp\MAH*.zip" | foreach-object{
$id = $_.Name.SubString(4,8);
if(-not (Test-Path c:\script\test\Master\MAH\$id)) {mkdir c:\script\test\Master\MAH\$id};
extract-zip $_ c:\script\test\Master\MAH\
if(-not (Test-Path c:\script\test\Working\MAH\$id)) {mkdir c:\script\test\Working\MAH\$id};
extract-zip $_ c:\script\test\Working\MAH\
}
Move-Item "C:\script\test\ftp\MAH*" "C:\script\test\ftp\archive"
#find all MAM files in the immediate directory
dir "C:\script\test\ftp\MAM*.zip" | foreach-object{
$id = $_.Name.SubString(4,8);
if(-not (Test-Path c:\script\test\Master\MAM\$id)) {mkdir c:\script\test\Master\MAM\$id};
extract-zip $_ c:\script\test\Master\MAM\$id
if(-not (Test-Path c:\script\test\Working\MAM\$id)) {mkdir c:\script\test\Working\MAM\$id};
extract-zip $_ c:\script\test\Working\MAM\$id
}
# Move-Item "C:\script\test\ftp\MAM*" "C:\script\test\ftp\archive"
you got me to thinking about the destination etc. so i started looking at some of the attempts early on in this project when i was trying to create the file structure then populate with 7zip command line interface... an attempt that failed miserably, and the light bulb went off.
ASKER
Do you know of a way to ensure a silent copy? ie overwrite existing file if copying a newer one?
this will be run through scheduler, so I must avoid a need for interaction.
this will be run through scheduler, so I must avoid a need for interaction.
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Thank you so much, and as I'm not using anything but running in powershell to "debug" i will certainly use your suggestion moving forward.
This is so much cleaner!! VERY much appreciated!
This is so much cleaner!! VERY much appreciated!
here's the script as optimal as possible:
function Extract-Zip
{
param([string]$zipfilename, [string] $destination)
if(test-path($zipfilename))
{
$shellApplication = new-object -com shell.application
$zipPackage = $shellApplication.NameSpace($zipfilename)
$destinationFolder = $shellApplication.NameSpace($destination)
$destinationFolder.CopyHere($zipPackage.Items())
}
}
cls
$archivefolder = "C:\script\test\ftp\archive"
if(-not (Test-Path $archivefolder)){
md $archivefolder
}
$postfixes = "MAC", "MAH", "MAM"
$postfixes | foreach {
$postfix = $_
$masterfolder = Join-Path "c:\script\test\Master\" $postfix
$workingfolder = Join-Path "c:\script\test\Working\" $postfix
$dirfolder = "C:\script\test\ftp\$postfix*.zip"
dir $dirfolder | foreach-object{
$filename = $_.BaseName
$srcfile = $_
$newdest = Join-Path $masterfolder $filename
if(-not (Test-Path ($newdest))){
#create directory
md $newdest
}
extract-zip $srcfile $newdest
$newdest = Join-Path $workingfolder $filename
if(-not (Test-Path ($newdest))){
#create directory
md $newdest
}
extract-zip $srcfile $newdest
Move-Item $srcfile $archivefolder
}
}
ASKER
excellent,
and I assume that adding .SubString (4,8) to the end of
$newdest = Join-Path $masterfolder $filename
as in
$newdest = Join-Path $masterfolder $filename.SubString( 4,8)
works as well as
$newdest = Join-Path $_ $filename.SubString (4,8)
from your previous post?
and by the way, I wish I had been using PowerGUI the whole time, instead of notepad. Great tip.
and I assume that adding .SubString (4,8) to the end of
$newdest = Join-Path $masterfolder $filename
as in
$newdest = Join-Path $masterfolder $filename.SubString( 4,8)
works as well as
$newdest = Join-Path $_ $filename.SubString (4,8)
from your previous post?
and by the way, I wish I had been using PowerGUI the whole time, instead of notepad. Great tip.
u don't need .SubString (4,8) cause $_.BaseName gives u only the file name without the extension.
so if the file is: c:\temp\jonny.zip
then $_.BaseName equals jonny.
and that is what u wish to add to the $destination folder, and i use join-path to do so.
good luck.
so if the file is: c:\temp\jonny.zip
then $_.BaseName equals jonny.
and that is what u wish to add to the $destination folder, and i use join-path to do so.
good luck.
ASKER
In doing so i actually get a cleaner folder name. For instance my zip file is actually quite long in name...
MAC.20120213-02.20.01
so i was using SubString (4,8) to extract only the yyyymmdd portion of the name so that the result would be <parent>\MAC\20120213 instead of <parent>\MAC\MAC.20120213- 02.20.01
although both results are good enough
MAC.20120213-02.20.01
so i was using SubString (4,8) to extract only the yyyymmdd portion of the name so that the result would be <parent>\MAC\20120213 instead of <parent>\MAC\MAC.20120213-
although both results are good enough
ASKER
and thanks again!