-
Notifications
You must be signed in to change notification settings - Fork 2
Expand file tree
/
Copy pathFileSystem.psm1
More file actions
345 lines (290 loc) · 13.7 KB
/
FileSystem.psm1
File metadata and controls
345 lines (290 loc) · 13.7 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
<#
.Synopsis
Test if a folder exist and create it if required
.Parameter folder
The folder to ensure
#>
Function Assert-Folder {
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)][string]$folder
)
if(!(Test-Path $folder)) {
Write-Verbose "Create the folder: '$folder'"
New-Item $folder -Type Directory -force
}
}
<#
.Synopsis
Download a remote file to a local folder
.Parameter url
The url where the originla file is stored
.Parameter targetFile
The target file path including the filename
#>
Function Get-RemoteFile {
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)][string]$url,
[Parameter(Mandatory=$true)][string]$targetFile
)
if (Test-Path $targetFile) {
Write-Verbose "The file $targetFile is allready present. Skipping."
}
else {
$webclient = New-Object System.Net.WebClient
Write-Verbose "Downloading '$url' to $targetFile"
try
{
$webclient.DownloadFile($url, $targetFile)
} catch [Exception]
{
echo $_.Exception|format-list -force
}
Write-Verbose "Download complete!"
}
}
<#
.Synopsis
Unzip a file
.Parameter zipPath
The zipped file
.Parameter destination
The where the uncompressed files will be downloaded
.Parameter createDestinationFolderIfNeeded
The filename to download
#>
Function Expand-Zip {
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true)][string]$zipPath,
[Parameter(Mandatory=$true)][string]$destination,
[switch]$createDestinationFolderIfNeeded
)
if($createDestinationFolderIfNeeded) {
Assert-Folder -folder $destination
}
#TODO : test if path is empty
Write-Verbose "Unzipping '$zipPath' to $destination ..."
$shell_app=new-object -com shell.application
$zip_file = $shell_app.namespace($zipPath)
$destinationNs = $shell_app.namespace($destination)
$destinationNs.Copyhere($zip_file.items())
Write-Verbose "Unzipping done!"
}
<#
.SYNOPSIS
Compares a reference directory with one or more difference directories.
.DESCRIPTION
Compare-Directory compares a reference directory with one ore more difference
directories. Files and directories are compared both on filename and contents
using a MD5hash.
Internally, Compare-Object is used to compare the directories. The behavior
and results of Compare-Directory is similar to Compare-Object.
.PARAMETER ReferenceDirectory
The reference directory to compare one or more difference directories to.
.PARAMETER DifferenceDirectory
One or more directories to compare to the reference directory.
.PARAMETER Recurse
Include subdirectories in the comparison.
.PARAMETER ExcludeFile
File names to exclude from the comparison.
.PARAMETER ExcludeDirectory
Directory names to exclude from the comparison. Directory names are
relative to the Reference of Difference Directory path
.PARAMETER ExcludeDifferent
Displays only the characteristics of compared files that are equal.
.PARAMETER IncludeEqual
Displays characteristics of files that are equal. By default, only
characteristics that differ between the reference and difference files
are displayed.
.PARAMETER PassThru
Passes the objects that differed to the pipeline. By default, this
cmdlet does not generate any output.
.EXAMPLE
Compare-Directory -reference "D:\TEMP\CompareTest\path1" -difference "D:\TEMP\CompareTest\path2" -ExcludeFile "web.config" -recurse
Compares directories "D:\TEMP\CompareTest\path1" and "D:\TEMP\CompareTest\path2" recursively, excluding "web.config"
Only differences are shown. Results:
RelativeBaseName MD5Hash SideIndicator Item
---------------- ------- ------------- ----
bin\site.dll 87A1E6006C2655252042F16CBD7FB41B => D:\TEMP\CompareTest\path2\bin\site.dll
index.html 02BB8A33E1094E547CA41B9E171A267B => D:\TEMP\CompareTest\path2\index.html
index.html 20EE266D1B23BCA649FEC8385E5DA09D <= D:\TEMP\CompareTest\path1\index.html
web_2.config 5E6B13B107ED7A921AEBF17F4F8FE7AF <= D:\TEMP\CompareTest\path1\web_2.config
bin\site.dll 87A1E6006C2655252042F16CBD7FB41B => D:\TEMP\CompareTest\path2\bin\site.dll
index.html 02BB8A33E1094E547CA41B9E171A267B => D:\TEMP\CompareTest\path2\index.html
index.html 20EE266D1B23BCA649FEC8385E5DA09D <= D:\TEMP\CompareTest\path1\index.html
web_2.config 5E6B13B107ED7A921AEBF17F4F8FE7AF <= D:\TEMP\CompareTest\path1\web_2.config
.EXAMPLE
Compare-Directory -reference "D:\TEMP\CompareTest\path1" -difference "D:\TEMP\CompareTest\path2" -ExcludeFile "web.config" -recurse -IncludeEqual
Compares directories "D:\TEMP\CompareTest\path1" and "D:\TEMP\CompareTest\path2" recursively, excluding "web.config".
Results include the items that are equal:
RelativeBaseName MD5Hash SideIndicator Item
---------------- ------- ------------- ----
bin == D:\TEMP\CompareTest\path1\bin
bin\site2.dll 98B68D681A8D40FA943D90588E94D1A9 == D:\TEMP\CompareTest\path1\bin\site2.dll
bin\site3.dll 9408C4B29F82260CBBA528342CBAA80F == D:\TEMP\CompareTest\path1\bin\site3.dll
bin\site4.dll 0616E1FBE12D468F611F07768D70C2EE == D:\TEMP\CompareTest\path1\bin\site4.dll
...
bin\site8.dll 87A1E6006C2655252042F16CBD7FB41B => D:\TEMP\CompareTest\path2\bin\site8.dll
index.html 02BB8A33E1094E547CA41B9E171A267B => D:\TEMP\CompareTest\path2\index.html
index.html 20EE266D1B23BCA649FEC8385E5DA09D <= D:\TEMP\CompareTest\path1\index.html
web_2.config 5E6B13B107ED7A921AEBF17F4F8FE7AF <= D:\TEMP\CompareTest\path1\web_2.config
.EXAMPLE
Compare-Directory -reference "D:\TEMP\CompareTest\path1" -difference "D:\TEMP\CompareTest\path2" -ExcludeFile "web.config" -recurse -ExcludeDifference
Compares directories "D:\TEMP\CompareTest\path1" and "D:\TEMP\CompareTest\path2" recursively, excluding "web.config".
Results only include the files that are equal; different files are excluded from the results.
.EXAMPLE
Compare-Directory -reference "D:\TEMP\CompareTest\path1" -difference "D:\TEMP\CompareTest\path2" -ExcludeFile "web.config" -recurse -Passthru
Compares directories "D:\TEMP\CompareTest\path1" and "D:\TEMP\CompareTest\path2" recursively, excluding "web.config" and returns NO comparison
results, but the different files themselves!
FullName
--------
D:\TEMP\CompareTest\path2\bin\site3.dll
D:\TEMP\CompareTest\path2\index.html
D:\TEMP\CompareTest\path1\index.html
D:\TEMP\CompareTest\path1\web_2.config
.LINK
Compare-Object
#>
function global:Compare-Directory
{
[CmdletBinding()]
param
(
[Parameter(Mandatory=$true, position=0, ValueFromPipelineByPropertyName=$true, HelpMessage="The reference directory to compare one or more difference directories to.")]
[System.IO.DirectoryInfo]$ReferenceDirectory,
[Parameter(Mandatory=$true, position=1, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="One or more directories to compare to the reference directory.")]
[System.IO.DirectoryInfo[]]$DifferenceDirectory,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Recurse the directories")]
[switch]$Recurse,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Files to exclude from the comparison")]
[String[]]$ExcludeFile,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Directories to exclude from the comparison")]
[String[]]$ExcludeDirectory,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Displays only the characteristics of compared objects that are equal.")]
[switch]$ExcludeDifferent,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Displays characteristics of files that are equal. By default, only characteristics that differ between the reference and difference files are displayed.")]
[switch]$IncludeEqual,
[Parameter(Mandatory=$false, ValueFromPipelineByPropertyName=$true, HelpMessage="Passes the objects that differed to the pipeline.")]
[switch]$PassThru
)
begin
{
function Get-MD5
{
[CmdletBinding(SupportsShouldProcess=$false)]
param
(
[Parameter(Mandatory=$true, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true, HelpMessage="file(s) to create hash for")]
[Alias("File", "Path", "PSPath", "String")]
[ValidateNotNull()]
$InputObject
)
begin
{
$cryptoServiceProvider = [System.Security.Cryptography.MD5CryptoServiceProvider]
$hashAlgorithm = new-object $cryptoServiceProvider
}
process
{
$hashByteArray = ""
#$item = Get-Item $InputObject -ErrorAction SilentlyContinue
#if ($item -is [System.IO.DirectoryInfo]) { throw "Cannot create hash for directory" }
#if ($item) { $InputObject = $item }
if ($InputObject -is [System.IO.FileInfo])
{
$stream = $null;
$hashByteArray = $null
try
{
$stream = $InputObject.OpenRead();
$hashByteArray = $hashAlgorithm.ComputeHash($stream);
}
finally
{
if ($stream -ne $null)
{
$stream.Close();
}
}
}
else
{
$utf8 = new-object -TypeName "System.Text.UTF8Encoding"
$hashByteArray = $hashAlgorithm.ComputeHash($utf8.GetBytes($InputObject.ToString()));
}
Write-Output ([BitConverter]::ToString($hashByteArray)).Replace("-","")
}
}
function Get-Files
{
[CmdletBinding(SupportsShouldProcess=$false)]
param
(
[string]$DirectoryPath,
[String[]]$ExcludeFile,
[String[]]$ExcludeDirectory,
[switch]$Recurse
)
$relativeBasenameIndex = $DirectoryPath.ToString().Length
# Get the files from the first deploypath
# and ADD the MD5 hash for the file as a property
# and ADD a filepath relative to the deploypath as a property
Get-ChildItem -Path $DirectoryPath -Exclude $ExcludeFile -Recurse:$Recurse | foreach {
$hash = ""
if (!$_.PSIsContainer) { $hash = Get-MD5 $_ }
# Added two new properties to the DirectoryInfo/FileInfo objects
$item = $_ |
Add-Member -Name "MD5Hash" -MemberType NoteProperty -Value $hash -PassThru |
Add-Member -Name "RelativeBaseName" -MemberType NoteProperty -Value ($_.FullName.Substring($relativeBasenameIndex)) -PassThru
# Test for directories and files that need to be excluded because of ExcludeDirectory
if ($item.PSIsContainer) { $item.RelativeBaseName += "\" }
if ($ExcludeDirectory | where { $item.RelativeBaseName -like "\$_\*" })
{
Write-Verbose "Ignore item `"$($item.Fullname)`""
}
else
{
Write-Verbose "Adding `"$($item.Fullname)`" to result set"
Write-Output $item
}
}
}
$referenceDirectoryFiles = Get-Files -DirectoryPath $referenceDirectory -ExcludeFile $ExcludeFile -ExcludeDirectory $ExcludeDirectory -Recurse:$Recurse
}
process
{
if ($DifferenceDirectory -and $referenceDirectoryFiles)
{
foreach($nextPath in $DifferenceDirectory)
{
$nextDifferenceFiles = Get-Files -DirectoryPath $nextpath -ExcludeFile $ExcludeFile -ExcludeDirectory $ExcludeDirectory -Recurse:$Recurse
###################################################
# Compare the contents of the two file/directory arrays and return the results
$results = @(Compare-Object -ReferenceObject $referenceDirectoryFiles -DifferenceObject $nextDifferenceFiles -ExcludeDifferent:$ExcludeDifferent -IncludeEqual:$IncludeEqual -PassThru:$PassThru -Property RelativeBaseName, MD5Hash)
if (!$PassThru)
{
foreach ($result in $results)
{
$path = $ReferenceDirectory
$pathFiles = $referenceDirectoryFiles
if ($result.SideIndicator -eq "=>")
{
$path = $nextPath
$pathFiles = $nextDifferenceFiles
}
# Find the original item in the files array
$itemPath = (Join-Path $path $result.RelativeBaseName).ToString().TrimEnd('\')
$item = $pathFiles | where { $_.fullName -eq $itemPath }
$result | Add-Member -Name "Item" -MemberType NoteProperty -Value $item
}
}
Write-Output $results
}
}
}
}