How to compare files in two .zip folder in Windows PowerShell - powershell

I can compare files in two different folder with the commands:
$test = get-childitem -recurse -path C:\test
$test1 = get-childitem -recurse -path C:\test1
$counter = (diff $test $test1).count
I would like to know how many differences between those two folders. This works.
However, now I would like to compare the filenames in two .zip files. Is it possible to compare the files inside two .zip files and I get a return value for the counter of different files?
Thank you so much.

I have tested .NET ZIP functionality on PowerShell V4. I suspect it would work on V3 but not on V2 (or V1).
Add-Type -AN System.IO.Compression.FileSystem
$zip1 = [IO.Compression.ZipFile]::OpenRead("c:\test\test1.zip")
$zip2 = [IO.Compression.ZipFile]::OpenRead("c:\test\test2.zip")
$names1 = $zip1.Entries.FullName
$names2 = $zip2.Entries.FullName
$counter = (diff $names1 $names2).count
$zip1.Dispose()
$zip2.Dispose()

Related

Using a filename for a variable and move similar files with Powershell

I am trying to write a powershell script that will look at a directory(c:\Temp) and look for files with exensions of .fin.
If it finds a file with the fin extension I need it to move all files that have the same first seven characters of that fin file to another directory(c:\Temp\fin).
There could be multiple .fin files at a time in that directory with files that need to be moved.
I have tried a few different things but I am new to anything like this. I have only used very basic powershell scripts or commands. While this might be basic(not sure) I am lost as to where to start.
You'll need to call Get-ChildItem twice. The first time to get the pattern you want to match the file names to and the second to get the files. You can then pipe the results of the second command to Move-Item. Here's an example of how to do that:
[CmdletBinding()]
param(
$DirectoryToScan,
$ExtensionToMatch = ".fin",
$TargetDirectory
)
$Files = Get-ChildItem -Path $DirectoryToScan -File
foreach ($File in $Files) {
if($File.Extension -eq $ExtensionToMatch) {
$PatternToMatch = "$($File.BaseName.Substring(0, 7))*$ExtensionToMatch"
Write-Verbose "PatternToMatch: $PatternToMatch"
$MatchedFiles = Get-ChildItem -Path $DirectoryToScan -Filter $PatternToMatch
}
$MatchedFiles | Move-Item -Destination $TargetDirectory
}
If you save the above into a file called Move-MatchingFiles.ps1 you can pass in your parameters Moving-MatchingFiles.ps1 -DirectoryToScan C:\Temp -TargetDirectory C:\Temp\fin. The ExtensionToMatch parameter is optional and only needed if you wanted to move a different type of file.

using Powershell to copy a directory (and subdirectory(s)) withouth overwriting/removing files

Working on a bit of a personal project.
I have my music collection on 3 different drives (read: different machines) including my NAS, Laptop, and Desktop. I need to be able to add new files to any of those 3 devices and have them sync upon request.
I have been attempting to use Robocopy.exe as it is a super easy one-liner to impliment, but it does not copy sub-folders/directories.
I am, i should mention, also pretty new to Powershell. The command does not need to be a one-liner, so if there is a way to impliment multi-level recursion to robocopy.exe all folders in a main directory, this would also work.
what i have now:
[string]$c = "c:\users\$env:username\music"
[string]$z = "z:\music"
robocopy.exe $c $z
robocopy.exe $z $c
i have a .cmd in my shell:startup to call execute this script 60 seconds after boot, and it works amazing for normal music files. The problem is, alot of my songs are in an album folder (such as Led Zeppelin box set) that would not make sense to scatter.
Any help would be much appreciated, as i have not found a good powershell method of copy/paste w/o exclusion / overwrite in the last few days freetime.
extra note: my two machines are running windows 10 so i will have access to latest powershell/ISE
You have to list the files in both locations and compare the lists. Then you iterate the list of differences.
$Folder1Contents = Get-ChildItem $Folder1Path
$Folder2Contents = Get-ChildItem $Folder2Path
$FolderDiffs = Compare-Object -ReferenceObject $Folder1Contents -DifferenceObject $Folder2Contents
$FolderDiffs | foreach {
$copyParams = #{
'Path' = $_.InputObject.FullName
}
if ($_.SideIndicator -eq '<=')
{
$copyParams.Destination = $Folder2Path
}
else
{
$copyParams.Destination = $Folder1Path
}
Copy-Item #copyParams
}

Powershell - Add folder/files to zip while excluding certain folders

I'm trying to feed the results of a Get-ChildItem call through io.compression.zipfile to create a zip file of "E:\Applications_Server_Test", excluding two folders "BACKUP" and "BACKUP2".
However, Powershell seems to be interpreting this as "$items = a string of directories and file names" instead of a recursive collection of directories and files I want to zip. I can find tutorials on using Get-ChildItem to exclude directories and I can find tutorials on how to zip a full directory or zip multiple directories but I can't find anything on zipping directories with exclusions. Can somebody tell me where I'm going wrong?
$source = "E:\Applications_Server_Test"
$destination = "E:\AST_Dump.zip"
$items = Get-ChildItem $source -Recurse | ?{ $_.fullname -notmatch "\\backup\\?" }
Add-Type -assembly "system.io.compression.filesystem"
[io.compression.zipfile]::CreateFromDirectory($items, $destination)
Thanks!
At the moment you are trying to archive the object $items, not the folder. Unfortunately this is not gonna work.
Try to move the backup folders at the same drive (this will just change records at the drive and not move any data), then to archive the whole "E:\Applications_Server_Test" folder and to move back the backup folders.
Other option is to use ZipArchive.CreateEntry method and to add file by file in to the archive. But this is not so elegant ;)

recursing folders and renaming files with create date added to filename

I am very much a newbie to powershell but have figured out some of what I need for a project at work. We have test result files (PDF, XLS. TXT, etc) in folders relating to test locations. Most folders have subfolders with files. The boss has mandated that the test date must be appended to the end of the file name (test_results.pdf -> test_results - 2014-05-06.pdf).
My code does get the creation date and appends it, however it only works on the folders in the source folder, also it is appending the creation date of the folder. I don't mind the date in the folder name if all the files ends up in the correct location. The files in the source subfolders are written to the new sub but without creation date appended.
Any help is greatly appreciated. Here's my code:
$SourceDir= 'C:\modem\'
$targetDir = 'C:\test2\'
set-location -path $sourceDir
$files = get-childitem -recurse
foreach ($file in $files)
{
[string]$strippedFileName =[io.path]::GetFileNameWithoutExtension($file);
[string]$extension = [io.Path]::GetExtension($file);
[string]$crtime=$file.CreationTime.toString(' - yyyy-MM-dd');
[string]$sourceFilePath = $file.DirectoryName;
[string]$DestinationFile = $targetDir + $sourcefilepath.trimstart($sourceDir) + "\" + $strippedFileName +$crtime + $extension;
Copy-Item $file.Fullname -Destination $DestinationFile -recurse -Force
}
Thank you,
tom
It sounds like it doesn't work for the files in the subfolders because you're creating subfolders in the destination directory with different names (date appended), but when you try to copy the files, you're using the original subfolder names in the path to the destination, so you're trying to copy them to locations that don't exist.
If that's the case, you might be wondering, then why do the files from the source subfolders get copied to the corresponding renamed subfolders, but without the date appended? Simple: because if you Copy-Item -Recurse a folder, all the contents get copied. The files in the subfolders aren't being copied individually by your foreach loop; they're being copied all at once by the last line of the loop each time you create a new (renamed) subfolder.
You can solve both problems simultaneously by simply exculding directories from the results of Get-ChildItem.
In PowerShell 1 and 2:
$files = Get-Childitem -Recurse | ?{$_.PSIsContainer}
In PowerShell 3 and up:
$files = Get-Childitem -Recurse -File
Also, it looks like you're coming from a background of .NET programming in a strongly type language (I'm guessing C# based on your accent). PowerShell is dynamically typed; there's no need (and no advantage) to casting all your variables as strings. The assigments will make them strings. Also, you don't need [IO.Path] to get the parts of the filename; they're attributes of the FileInfo objects returned by Get-ChildItem.
You can write you loop like this:
foreach ($file in $files)
{
$strippedFileName = $file.BaseName;
$extension = $file.Extension;
$crtime=$file.CreationTime.toString(' - yyyy-MM-dd');
$sourceFilePath = $file.DirectoryName;
$DestinationFile = $targetDir + $sourcefilepath.TrimStart($sourceDir) + "\" + $strippedFileName +$crtime + $extension;
Copy-Item $file.FullName -Destination $DestinationFile -Recurse -Force
}

Powershell: processing files in two folders based on what's in them

I have two directories: c:\Rar and c:\unRared
Rar - contains hundreds of RAR'ed files. Only one file inside the RAR. File inside the archive is with *.TRN extension.
UnRared has unarchived files (hundreds of files with *.TRN extension)
I've been trying to create a Powershell script to extract only files that have not been extracted already.
can't you just supply parameters to whatever compression program you have telling it not to overwrite existing files?
Knocked this out on my own...well, not really, with the help of developer
$dir1='C:\temp\aaa'
$dir2='C:\temp\bbb'
$CmdPath = "C:\Program Files (x86)\WinRAR\RAR.exe"
$Files2Extract = get-childitem -path 'C:\temp\aaa' -recurse -name -filter *.rar
#$d2 = get-childitem -path $dir2 -recurse
foreach($file in $Files2Extract){
$justname = $dir2+'\\'+(split-path $file -leaf).split(".")[0]+'.trn'
if(!(Test-Path -path $justname)) {
&$CmdPath e $file $dir2
}
}