I have a PowerShell Script:
$path = "X"
$destination = "Y"
while (1 -eq 1) {
if (Test-Path $path) {
$shell_app = New-Object -COM Shell.Application
$files = Get-ChildItem -Path $path -Filter *.zip -Recurse
foreach ($file in $files) {
$zip_file = $shell_app.NameSpace($file.FullName)
$copyHere = $shell_app.NameSpace($destination)
$copyHere.CopyHere($zip_file.Items())
}
} else {
}
}
What I want to achieve is: I want the script to unzip all the files when it lands on the folder. But the script keeps on trying to unzip files it has already unzipped. Basically it keeps on looping. I want it to unzip all the file once it land on the folder and then stop the process.
Related
I am trying to create myself a powershell script that has mainly two tasks - one after the other.
Initial assumptions: it runs where it performs the following tasks.
Trace all the files, those that are folders - make a zip of them, then after making the archive, delete them. Objective accomplished.
Write to the file the names of all files in the folder (after completing point 1) but check if the given file has the extension of *.zip
a) if it has extension of *.zip then it should be saved in .txt file like "uresoruce = foo/file.zip"
b) if it doesn't have extension *.zip then it should be saved to a .txt file like this "resoruce = foo/file2.jar"
c) since the script is started from the place where all the files are, it will probably also be saved to a file, I would like to avoid this
Suppose we have some files in a folder after compiling, and we don't have any folder inside. The .txt file should look like the following:
uresource = plugins/Liula_1.0.0.0.zip
uresource = plugins/Liborts_3.7.1.0.zip
uresource = plugins/Liwer_1.2.0.0.zip
resource = plugins/o0.I20100512-1500.jar
resource = plugins/or.v20100505-1235.jar
The script I managed to write so far:
## set current path
$path = (Resolve-Path .\).Path
## dirs in a path
$source = Get-ChildItem -Path $path -Filter "" -Directory
$files = Get-ChildItem $path
Add-Type -assembly "system.io.compression.filesystem"
Foreach ($s in $source) {
$destination = Join-path -path $path -ChildPath "$($s.name).zip"
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $destination)
Remove-Item $s -Recurse
}
# This does not working!!! :/
Foreach ($f in $files) {
$extn = [IO.Path]::GetExtension($f)
if ($extn -eq ".zip" ) {
$outfile = "uresource = plugins/" + $f.Name
}
else {
$outfile = "resource = plugins/" + $f.Name
}
}
As #Santiago Squarzon rightly pointed out I did not do anything with this variable. I got a little confused because before I did it only for out-file I didn't use -append and in fact I got the last value in .txt. Now I made my first script in ph, it works like a dream ;)
## set current path
$path = (Resolve-Path .\).Path
## dirs in a path
$source = Get-ChildItem -Path $path -Filter "" -Directory
$files = Get-ChildItem $path
Add-Type -assembly "system.io.compression.filesystem"
## create zip and delete other dirs
Foreach ($s in $source) {
$destination = Join-path -path $path -ChildPath "$($s.name).zip"
[io.compression.zipfile]::CreateFromDirectory($s.fullname, $destination)
Remove-Item $s -Recurse
}
## output filename in .txt
$logFile = "$pwd\logfile.txt"
Foreach ($f in $files) {
$extn = [IO.Path]::GetExtension($f)
if ($extn -eq ".zip" ) {$outfile = "uresource = plugins/$f"}
else {$outfile = "resource = plugins/$f"}
$outfile | Out-File -Append $logFile
}
I want to check .jpg file in the 2nd folder. 2nd folder has some subfolder. if .jpg exist in the subfolder of 2nd folder, I will copy a file from 1st folder to subfolder of 2nd folder based on the base name. I can do this part refer to this answer
How to copy file based on matching file name using PowerShell?
But I want to do limitation while I copy a file from 1st folder. I will NOT copy the file, if I already copy the same file from 1st folder to 2nd folder 3 times.
This is the code from the reference.
$Job_Path = "D:\Initial"
$JobError = "D:\Process"
Get-ChildItem -Path "$OpJob_Path\*\*.jpg" | ForEach-Object {
$basename = $_.BaseName.Substring(15)
$job = "$Job_Path\${basename}.png"
if (Test-Path $job) {
$timestamp = Get-Date -Format 'yyyyMMddhhmmss'
$dst = Join-Path $_.DirectoryName "${timestamp}_${basename}.gif"
Copy-Item $job $dst -Force
}
Anyone can help me to solve this problem please. Thank you.
Updated
$Job_Path = "D:\Initial"
$JobError = "D:\Process"
Get-ChildItem -Path "$OpJob_Path\*\*.jpg" | ForEach-Object {
$basename = $_.BaseName.Substring(15)
$job = "$Job_Path\${basename}.png"
if (Test-Path $job) {
$timestamp = Get-Date -Format 'yyyyMMddhhmmss'
$dst = Join-Path $_.DirectoryName "${timestamp}_${basename}.gif"
$Get = (Get-ChildItem -Name "$OpJob_Path\*\*$basename.jpg*" | Measure-Object).Count
$Get
if ($Get -eq "3") {
Write-Host "Continue Other Process"
NEXT_PROCESS
} else {
Write-Host "Less than 3"
}
Copy-Item $job $dst -Force
}
$Get is not a hashtable, and it's also not keeping track of what's been copied already. You need to define the hashtable outside the loop
$copy_count = #{}
Get-ChildItem -Path "$OpJob_Path\*\*.jpg" | ForEach-Object {
...
}
and then update it whenever you copy a file
if ($copy_count[$_.Name] -le 3) {
Copy-Item ...
$copy_count[$_.Name]++
} else {
...
}
Currently, I am writing a script that moves PDF files that are wrongfully zipped to a certain folder. I have achieved that. The next thing I need to get to work, is that the zipped .pdf files get unzipped into a different folder.
This is my whole script. Everything except for the last 2 lines is dedicated to finding the PDF files that are zipped and moving them.
In the first parts, the script checks the first few bytes of every pdf file in the folder. If they start with "PK*", they are zip files and get moved to the zipped folder.
For every PDF/zip file, there is one associated HL7 file in the folder next to it.
These also need to get moved to the same folder. From there the zip files need to be unzipped and relocated to "unzipped"
The last 2 lines are for unzipping.
$pdfDirectory = 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\struktur_id_1225\ext_dok'
$newLocation = 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\Zip'
Get-ChildItem "$pdfDirectory" -Filter "*.pdf" | foreach {
if ((Get-Content $_.FullName | select -First 1 ) -like "PK*") {
$HL7 = $_.FullName.Replace("ext_dok","MDM")
$HL7 = $HL7.Replace(".pdf",".hl7")
move $_.FullName $newLocation;
move $HL7 $newLocation
}
}
Get-ChildItem 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\Zip' |
Expand-Archive -DestinationPath 'Z:\Documents\16_Med._App\Auftraege\PDFPrzemek\Zip\unzipped' -Force
This, sadly, doesn't work.
I suspect that it's because these files dont have the .zip extension. The only Filter that works for Expand-Archive is .zip.
So I need to find a way to get this function to unzip the files, even though they dont have the fitting extension...
Like #Ansgar said this would be the way to go:
Param (
$SourcePath = 'C:\Users\xxx\Downloads\PDF',
$ZipFilesPath = 'C:\Users\xxx\Downloads\ZIP',
$UnzippedFilesPath = 'C:\Users\xxx\Downloads\Unzipped'
)
$VerbosePreference = 'Continue'
#region Test folders
#($SourcePath, $ZipFilesPath, $UnzippedFilesPath) | Where-Object {
-not (Test-Path -LiteralPath $_)
} | ForEach-Object {
throw "Path '$_' not found. Make sure that the folders exist before running the script."
}
#endregion
#region Get all files with extension .pdf
$Params = #{
Path = Join-Path -Path $SourcePath -ChildPath 'ext_dok'
Filter = '*.pdf'
}
$PDFfiles = Get-ChildItem #Params
Write-Verbose "Got $($PDFfiles.count) files with extension '.pdf' from '$($Params.Path)'"
#endregion
#region Move PDF and HL7 files
$MDMpath = Join-Path -Path $SourcePath -ChildPath 'MDM'
foreach ($PDFfile in ($PDFfiles | Where-Object {
(Get-Content $_.FullName | Select-Object -First 1) -like 'PK*'})
) {
$MoveParams = #{
Path = $PDFfile.FullName
Destination = Join-Path -Path $ZipFilesPath -ChildPath ($PDFfile.BaseName + '.zip')
}
Move-Item #MoveParams
Write-Verbose "Moved file '$($MoveParams.Path)' to '$($MoveParams.Destination)'"
$GetParams = #{
Path = Join-Path -Path $MDMpath -ChildPath ($PDFfile.BaseName + '.hl7')
ErrorAction = 'Ignore'
}
if ($HL7file = Get-Item #GetParams) {
$MoveParams = #{
Path = $HL7file
Destination = $ZipFilesPath
}
Move-Item #MoveParams
Write-Verbose "Moved file '$($MoveParams.Path)' to '$($MoveParams.Destination)$($HL7file.Name)'"
}
}
#endregion
#region Unzip files
$ZipFiles = Get-ChildItem -Path $ZipFilesPath -Filter '*.zip' -File
foreach ($ZipFile in $ZipFiles) {
$ZipFile | Expand-Archive -DestinationPath $UnzippedFilesPath -Force
Write-Verbose "Unzipped file '$($ZipFile.Name)' in folder '$UnzippedFilesPath'"
}
#endregion
Some tips:
Add a Param () clause at the beginning of the script to contain all your variables that can change.
Try to use the full parameter name to clearly indicate what is what. Use Get-ChildItem -Path xxx instead of Get-ChildItem xxx.
Use hash tables for long parameters. This makes the code more compact in width and more easily to read.
Use #region and #endregion to group your code.
hi i am trying to unzip folders and sub folders i have tried different ways and script but no luck.
Can some one help on this
$Date = Get-Date
#
$folder_date = $Date.ToString("yyyy-MM-dd_HHmmss")
$content = get-childitem 'C:\Deployments'
$sortedContent = $content | Sort-Object LastWriteTime -Descending
# 1. LIST BACKUPS
write-host "This is the list of all the Deployments :"
$count = 1
foreach ($item in $sortedContent)
{
#Edit: Now with auto-incrementing counter
Write-Host ("{0}: {1}" -f $count, $item.Name)
$count++
}
$itemNumber = Read-Host "Please select which deployments you want to copy "
$itemNumber = $itemNumber -1
if($sortedContent[$itemNumber].PSIsContainer -eq $true)
{
$src = $sortedContent[$itemNumber].FullName + "\"
$Date = Get-Date
$folder_date = $Date.ToString("yyyy-MM-dd_HHmm")
$tempPath = 'C:\_Temp\Restore' + $folder_date
if (!(Test-Path -path $tempPath))
{
New-Item $tempPath -type directory
}
$TabletzipPath = $src + "table.zip"
$AdminzipPath = $src + "admin.zip"
.\unzip.ps1 $src $tempPath
.\unzip.ps1 $TabletzipPath $tempPath
.\unzip.ps1 $AdminzipPath $tempPath
}
$Shell = new-object -com shell.application
$Zip = $Shell.NameSpace($PathToZip)
ForEach($Item in $Zip.items())
{
$Shell.Namespace($ExtractPath).copyhere($Item)
}
If your just looking for an easy & quick way of doing this.
You can use this function:
Unzip-File -File C:\location.zip -Destination E:\destination
Need this script:
http://gallery.technet.microsoft.com/scriptcenter/PowerShell-Function-to-727d6200
Using jar unzipping: copy-paste it into PowerShell ISE or create a .ps1 file with this code:
#choose directory where your script is
cd $PSScriptRoot
#do for each file in your directory, -recurse stands for all subfolders, *.jar stands for all files with jar extension
foreach ($file in (dir -Recurse *.jar))
{
#Uncomment this to check files this script is going to unzip (don't forget to comment 7z line below to avoid operation)
#Write-Host ("Dir for file " + $file.Name + " is " + $file.Directory)
#put here full path to 7z if there is no system env (or just make it) for that
#x stands for eXtract files with full paths
#-o is for output folder (example of usage -oc:\test\)
7z x $file.FullName ("-o"+$file.Directory)
}
It should unzip everything you need directly to the folder where your .jar (or any other archive) is.
I need to unzip a specific directory from a zipfile.
Like for example extract the directory 'test\etc\script' from zipfile 'c:\tmp\test.zip' and place it in c:\tmp\output\test\etc\script.
The code below works but has two quirks:
I need to recursively find the directory ('script') in the zip file (function finditem) although I already know the path ('c:\tmp\test.zip\test\etc\script')
With CopyHere I need to determine the targetdirectory, specifically the 'test\etc' part manually
Any better solutions? Thanks.
The code:
function finditem($items, $itemname)
{
foreach($item In $items)
{
if ($item.GetFolder -ne $Null)
{
finditem $item.GetFolder.items() $itemname
}
if ($item.name -Like $itemname)
{
return $item
}
}
}
$source = 'c:\tmp\test.zip'
$target = 'c:\tmp\output'
$shell = new-object -com shell.application
# find script folder e.g. c:\tmp\test.zip\test\etc\script
$item = finditem $shell.NameSpace($source).Items() "script"
# output folder is c:\tmp\output\test\etc
$targetfolder = Join-Path $target ((split-path $item.path -Parent) -replace '^.*zip')
New-Item $targetfolder -ItemType directory -ErrorAction Ignore
# unzip c:\tmp\test.zip\test\etc\script to c:\tmp\output\test\etc
$shell.NameSpace($targetfolder).CopyHere($item)
I don't know about most elegant, but with .Net 4.5 installed you could use the ZipFile class from the System.IO.Compression namespace:
[Reflection.Assembly]::LoadWithPartialName('System.IO.Compression.FileSystem') | Out-Null
$zipfile = 'C:\path\to\your.zip'
$folder = 'folder\inside\zipfile'
$dst = 'C:\output\folder'
[IO.Compression.ZipFile]::OpenRead($zipfile).Entries | ? {
$_.FullName -like "$($folder -replace '\\','/')/*"
} | % {
$file = Join-Path $dst $_.FullName
$parent = Split-Path -Parent $file
if (-not (Test-Path -LiteralPath $parent)) {
New-Item -Path $parent -Type Directory | Out-Null
}
[IO.Compression.ZipFileExtensions]::ExtractToFile($_, $file, $true)
}
The 3rd parameter of ExtractToFile() can be omitted. If present it defines whether existing files will be overwritten or not.
As far as the folder location in a zip is known, the original code can be simplified:
$source = 'c:\tmp\test.zip' # zip file
$target = 'c:\tmp\output' # target root
$folder = 'test\etc\script' # path in the zip
$shell = New-Object -ComObject Shell.Application
# find script folder e.g. c:\tmp\test.zip\test\etc\script
$item = $shell.NameSpace("$source\$folder")
# actual destination directory
$path = Split-Path (Join-Path $target $folder)
if (!(Test-Path $path)) {$null = mkdir $path}
# unzip c:\tmp\test.zip\test\etc\script to c:\tmp\output\test\etc\script
$shell.NameSpace($path).CopyHere($item)
Windows PowerShell 5.0 (included in Windows 10) natively supports extracting ZIP files using Expand-Archive cmdlet:
Expand-Archive -Path Draft.Zip -DestinationPath C:\Reference