Trying to extract files from zip powershell excluding .inf - powershell

Trying to extract just .sql files from zip powershell
Referring to the above link, a powershell script was made to extract only .sql files.
Is there a way to reverse this, so it extracts everything from the Zip file apart from .Inf files.
Any help will be greatly appreciated, as my powershell skills are next to none.
$shell = New-Object -COM 'Shell.Application'
$zipfile = 'C:\Powershell\From here\1-5'
$destination = 'C:\Powershell\To Here'
$zip = $shell.NameSpace($zipfile)
$zip.Items() | ? { $_.Path -notlike '*.inf' } | % {
$shell.NameSpace($destination).CopyHere($_)
}

It would be helpful if you posted your code but in general you could use an operator like -notlike or -notmatch to achieve what you want to do.

Related

Copy subset of files keeping folder structure using Powershell

Looking for some Powershell help with a copying challenge.
I need to copy all MS Office files from a fairly large NAS (over 4 million of them and a little over 5tb) to another drive, retaining the existing folder structure where a file is copied.
I have a text file of all the common Office file types (about 40 of them) - extns.txt
At this stage, being a good StackExchanger, I'd post the script I've got so far, but I've spent best part of a day on this and, not only is what I've got embarrassingly awful, I suspect that even the basic algorithm is wrong.
I started to gci the entire tree on the old NAS, once for each file type
Then I thought it would be better to traverse once and compare every file to the list of valid types.
Then I got into a complete mess about rebuilding the folder structure. I started by splitting on '\' and iterating through the path then wasted an hour of searching because I thought I remembered reading about a simple way to duplicate a path if it doesn't exist.
Another alternative is that I dump out a 4 million line text file of all the files (with full path) I want to copy (this is easy as I imported the entire structure into SQL Server to analyse what was there) and use that as a list of sources
I'm not expecting a 'please write the codez for me' answer but some pointers/thoughts on the best way to approach this would be appreciated.
I'm not sure if this is the best approach, but the below script is a passable solution to the least.
$sourceRootPath = "D:\Source"
$DestFolderPath = "E:\Dest"
$extensions = Get-Content "D:\extns.txt"
# Prefix "*." to items in $extensions if it doesn't already have it
$extensions = $extensions -replace "^\*.|^","*."
$copiedItemsList = New-Object System.Collections.ArrayList
foreach ( $ext in $extensions ) {
$copiedItems = Copy-Item -Path $sourceRootPath -Filter $ext -Destination $DestFolderPath -Container -Recurse -PassThru
$copiedItems | % { $copiedItemsList.Add($_) | Out-Null }
}
$copiedItemsList = $copiedItemsList | select -Unique
# Remove Empty 'Deletable' folders that get created while maintaining the folder structure with Copy-Item cmdlet's Container switch
While ( $DeletableFolders = $copiedItemsList | ? { ((Test-Path $_) -and $_.PSIsContainer -eq $true -and ((gci $_ | select -first 1).Count -eq 0)) } ) {
$DeletableFolders | Remove-Item -Confirm:$false
}
The Copy-Item's -Container switch is going to preserve the folder structure for us. However, we may encounter empty folders with this approach.
So, I'm using an arraylist named $copiedItemsList to add the copied objects into, which I will later use to determine empty 'Deletable' folders which are then removed at the end of the script.
Hope this helps!

Creating Zip files using PowerShell

I have these below files at a location C:\Desktop\Mobile.
Apple_iphone6.dat
Apple_iphone7.dat
Samsung_edge7.dat
Samsung_galaxy.dat
Sony_experia.dat
Sony_M2.dat
I need to create a script that writes the similar files into a single zip. So files Apple_iphone6.dat and Apple_iphone7.dat must be into single zip.
So the final zip files created would be:
Apple_Files_Timestamp.zip
Samsung_Files_Timestamp.zip
Sony_Files_Timestamp.zip
I tried this
Get-ChildItem C:\Desktop\Mobile -Recurse -File -Include *.dat | Where-Object { $_.LastWriteTime -lt $date } | Compress-Archive -DestinationPath C:\Desktop\Mobile
But it gives me error 'Compress-Archive' is not recognized as the name of a cmdlet.
How can I get this code work?
You have two problems, I will try to summarize both of them.
1. Compress files
In order to use Compress-Archive command you need to have PowerShell 5 as already commented by #LotPings. You can:
run your script on Windows 10 machine, or Server 2016 which are coming with v5
download and install PoSh 5, see details on MSDN
If you cannot do either of those, you can
install some module from PowerShell gallery that provides similar functionality via 7-zip tool. Search resultes are here. Download and check those modules before use!
use .NET 4.5 class, check answer here on Stack Overflow
2. Group files
Once you group files, you can easily pipe them to compressing command, similar as you already tried. Proper grouping would be achieved with something like this:
$Files = Get-ChildItem 'C:\Desktop\Mobile'
$Groups = $Files | ForEach-Object {($_.Name).split('_')[0]} | Select-Object -Unique
foreach ($Group in $Groups) {
$Files | where Name -Match "^$Group" | Compress-Archive "C:\Desktop\Mobile\$Group.7z"
}
Pre Powershell v5 you can use this. No additional downloads needed.
$FullName = "Path\FileName"
$Name = CompressedFileName
$ZipFile = "Path\ZipFileName"
$Zip = [System.IO.Compression.ZipFile]::Open($ZipFile,'Update')
[System.IO.Compression.ZipFileExtensions]::CreateEntryFromFile($Zip,$FullName,$Name,"optimal")
$Zip.Dispose()
With Powershell 2.0 you can't use Compress-Archive, you need download the original terminal executables to zip and unzip files from here.
You can use:
zip <path> <zip_name> -i <pattern_files>
In your example:
zip "C:\Desktop\Mobile" Apple_Files_Timestamp.zip -i Apple*.dat
zip "C:\Desktop\Mobile" Samsung_Files_Timestamp.zip -i Samsung*.dat
zip "C:\Desktop\Mobile" Sony_Files_Timestamp.zip -i Sony*.dat
If you need use adittional zip options, visit zip manual.
The following script does the grouping,
the zipping command depends on your chosen zipper.
$TimeStamp = Get-Date -Format "yyyyMMddhhmmss"
Get-ChildItem *.dat|
Group-Object {($_.Name).split('_')[0]}|
ForEach-Object {
$Make = $_.Name
Foreach($File in $_.Group){
"{0,20} --> {1}_Files_{2}.zip" -f $File.Name,$Make,$TimeStamp
}
}
Sample output:
> .\SO_44030884.ps1
Samsung_edge7.dat --> Samsung_Files_20170517081753.zip
Samsung_galaxy.dat --> Samsung_Files_20170517081753.zip
Apple_iphone6.dat --> Apple_Files_20170517081753.zip
Apple_iphone7.dat --> Apple_Files_20170517081753.zip
Sony_M2.dat --> Sony_Files_20170517081753.zip
Sony_experia.dat --> Sony_Files_20170517081753.zip
This link might help Module to Synchronously Zip and Unzip using PowerShell 2.0

Use PowerShell to generate a list of files and directories

I'm writing a PowerShell script to make several directories and copy a bunch of files together to "compile" some technical documentation. I'd like to generate a manifest of the files and directories as part of the readme file, and I'd like PowerShell to do this, since I'm already working in PowerShell to do the "compiling".
I've done some searching already, and it seems that I need to use the cmdlet "Get-ChildItem", but it's giving me too much data, and I'm not clear on how to format and prune out what I don't want to get my desired results.
I would like an output similar to this:
Directory
file
file
file
Directory
file
file
file
Subdirectory
file
file
file
or maybe something like this:
+---FinGen
| \---doc
+---testVBFilter
| \---html
\---winzip
In other words, some kind of basic visual ASCII representation of the tree structure with the directory and file names and nothing else. I have seen programs that do this, but I am not sure if PowerShell can do this.
Can PowerShell do this? If so, would Get-ChildItem be the right cmdlet?
In your particular case what you want is Tree /f. You have a comment asking how to strip out the part at the front talking about the volume, serial number, and drive letter. That is possible filtering the output before you send it to file.
$Path = "C:\temp"
Tree $Path /F | Select-Object -Skip 2 | Set-Content C:\temp\output.tkt
Tree's output in the above example is a System.Array which we can manipulate. Select-Object -Skip 2 will remove the first 2 lines containing that data. Also, If Keith Hill was around he would also recommend the PowerShell Community Extensions(PSCX) that contain the cmdlet Show-Tree. Download from here if you are curious. Lots of powerful stuff there.
The following script will show the tree as a window, it can be added to any form present in the script
function tree {
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Windows.Forms")
[void][System.Reflection.Assembly]::LoadWithPartialName("System.Drawing")
# create Window
$Form = New-Object System.Windows.Forms.Form
$Form.Text = "Files"
$Form.Size = New-Object System.Drawing.Size(390, 390)
# create Treeview-Object
$TreeView = New-Object System.Windows.Forms.TreeView
$TreeView.Location = New-Object System.Drawing.Point(48, 12)
$TreeView.Size = New-Object System.Drawing.Size(290, 322)
$Form.Controls.Add($TreeView)
###### Add Nodes to Treeview
$rootnode = New-Object System.Windows.Forms.TreeNode
$rootnode.text = "Root"
$rootnode.name = "Root"
[void]$TreeView.Nodes.Add($rootnode)
#here i'm going to import the csv file into an array
$array=#(Get-ChildItem -Path D:\personalWorkspace\node)
Write-Host $array
foreach ( $obj in $array ) {
Write-Host $obj
$subnode = New-Object System.Windows.Forms.TreeNode
$subnode.text = $obj
[void]$rootnode.Nodes.Add($subnode)
}
# Show Form // this always needs to be at the bottom of the script!
$Form.Add_Shown({$Form.Activate()})
[void] $Form.ShowDialog()
}
tree
In Windows, navigate to the directory of interest
Shift+ right click mouse -> Open PowerShell window here
Get-ChildItem | tree /f > tree.log
The best and clear way for me is:
PS P:\> Start-Transcript -path C:\structure.txt -Append
PS P:\> tree c:\test /F
PS P:\> Stop-Transcript
You can use command Get-ChildItem -Path <yourDir> | tree >> myfile.txt this will output tree-like structure of a directory and write it to "myfile.txt"

PowerShell script - check multiple PC's for file existence then get that file version

My PowerShell skills are in their infancy so please bear with me.
What I need to do is take a list of PC's from a text file and check for file existence. Once that has been determined, I need to take those PC's that have the file and check the file for its FileVersion. Then in the end, output that to a CSV file.
Here's what I have and I'm not really sure if this is even how I should be going about it:
ForEach ($system in (Get-Content C:\scripts\systems.txt))
if ($exists in (Test-Path \\$system\c$\Windows\System32\file.dll))
{
Get-Command $exists | fl Path,FileVersion | Out-File c:\scripts\results.csv -Append
}
Not bad for a starter script, you got it almost right. Let's amend it a bit. To get the version info we'll just get a working code from another an answer.
ForEach ($system in (Get-Content C:\scripts\systems.txt)) {
# It's easier to have file path in a variable
$dll = "\\$system\c`$\Windows\System32\file.dll"
# Is the DLL there?
if ( Test-Path $dll){
# Yup, get the version info
$ver = [System.Diagnostics.FileVersionInfo]::GetVersionInfo($dll).FileVersion
# Write file path and version into a file.
Add-Content -path c:\scripts\results.csv "$dll,$ver"
}
}

Powershell - modify items in ZIP archive

I read about extracting ZIP archives on Stackoverflow which results in creating following script:
$shell_app=New-Object -com shell.application
Get-ChildItem -name *.zip | ForEach-Object {
$zip_file=$shell_app.NameSpace((Get-Location).path + " \$_")
$destination=$shell_app.NameSpace((Get-Location).path)
$destination.copyhere($zip_file.items()) }
Now I'm interested in manipulating on items in this archive - for example before I unpack all those files, I want to add to their filenames, name of archive.
AS I check, I can get it (with .zip extenston which I want to remove) by simply entering
%zip_file.title
but I'm not aware how to modify file names. Could anybody help or give sufficient resources?
I don't think you can do that with the shell object alone. I think you'll have to extract the file files and then rename using PowerShell. Here's my test code that works. Quick and dirty but it does the trick.
$zip="c:\work\brain.zip"
$shell_app=New-Object -com shell.application
$zip_file=$shell_app.NameSpace($zip)
$destination=$shell_app.NameSpace("G:\test")
$zip_file.items() | foreach {
$newname="{0}_{1}" -f $zip_file.Title,$_.name
Write-Host "Extracting $newname" -ForegroundColor Green
$destination.copyhere($_)
$oldfile=Join-path $destination.Self.Path -ChildPath $_.name
Rename-Item -Path $oldfile -NewName $newname -passthru
}
Why not create a subfolder for each zipfile in the destination?