CoreePower.Common.IO.ps1
<#
.SYNOPSIS Recursively copies files and directories from a source directory to a destination directory. .DESCRIPTION The `Copy-Recursive` function allows you to copy files and directories from a specified source directory to a destination directory. It performs a recursive copy operation, preserving the directory structure of the source directory. .PARAMETER Source Specifies the path to the source directory. This is the directory from which files and directories will be copied. .PARAMETER Destination Specifies the path to the destination directory. This is the directory where the files and directories from the source directory will be copied to. .NOTES - This function performs a recursive copy, copying all files and directories from the source directory to the destination directory. - The directory structure of the source directory is preserved in the destination directory. - If the destination directory does not exist, it will be created. - If a file or directory with the same name already exists in the destination directory, it will be overwritten. - The function accepts the alias 'copyrec' for easier use. .EXAMPLE PS C:\> Copy-Recursive -Source 'C:\SourceFolder' -Destination 'C:\DestinationFolder' This example copies all files and directories from 'C:\SourceFolder' to 'C:\DestinationFolder', preserving the directory structure. #> function Copy-Recursive { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] [alias("copyrec")] param ( [string]$Source, [string]$Destination ) New-Directory -Directory $Destination Get-ChildItem $Source -Recurse | Foreach-Object { $targetPath = $_.FullName -replace [regex]::Escape($Source), $Destination if ($_.PSIsContainer) { New-Item -ItemType Directory -Path $targetPath -Force | Out-Null } else { Copy-Item $_.FullName -Destination $targetPath -Force | Out-Null } } } <# .SYNOPSIS Creates a new temporary directory in the AppData\Local\Temp directory. .DESCRIPTION The `New-TempDirectory` function creates a new temporary directory in the AppData\Local\Temp directory. It generates a unique identifier using `[System.Guid]::NewGuid().ToString()` and combines it with the AppData\Local\Temp path to create a unique directory path. If the directory does not exist, it is created using `New-Item`. .NOTES - The function provides a convenient way to generate and create a new temporary directory. - The generated temporary directory path is returned as the output. - This function uses the `LocalApplicationData` folder within the AppData directory to ensure the creation of the temporary directory in the user's local application data. - The function accepts the alias 'newtmpdir' for easier use. .EXAMPLE PS C:\> New-TempDirectory This example creates a new temporary directory in the AppData\Local\Temp directory and returns the path of the newly created directory. #> function New-TempDirectory { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] [Alias("newtmpdir")] param () $tempDirectoryPath = Join-Path ([Environment]::GetFolderPath('LocalApplicationData')) 'Temp' | Join-Path -ChildPath ([System.Guid]::NewGuid().ToString()) if (-not (Test-Path $tempDirectoryPath)) { New-Item -ItemType Directory -Path $tempDirectoryPath -Force | Out-Null } return $tempDirectoryPath } <# .SYNOPSIS Creates a new directory if it does not already exist. .DESCRIPTION The New-Directory function creates a new directory specified by the 'Directory' parameter. If the directory already exists, the function will not create a new one. If a file path is supplied instead of a directory, the function will move up one directory level and attempt to create the directory there. .PARAMETER Directory The path of the directory to be created. This parameter is mandatory. If a file path is supplied, the function will use the parent directory of that file as the path to create the new directory. .EXAMPLE New-Directory -Directory "C:\Temp\NewFolder" This will create a new directory named 'NewFolder' inside the 'C:\Temp' directory if it does not already exist. .EXAMPLE New-Directory -Directory "C:\Temp\myfile.txt" This will create a new directory in 'C:\Temp' since a file path was supplied. #> function New-Directory { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] param ( [Parameter(Mandatory = $true)] [string]$Directory ) if (-not(Test-Path -Path $Directory -PathType Container)) { New-Item -ItemType Directory -Path $Directory -Force | Out-Null } if (Test-Path -Path $Directory -PathType Leaf) { $Directory = [System.IO.Path]::GetDirectoryName($Directory) $Directory = New-Directory -Directory $Directory } return $Directory } function Remove-TempDirectory { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] [Alias("rmtmpdir")] param ( [Parameter(Mandatory = $true)] [string]$TempDirectory ) if (Test-Path -Path $TempDirectory -PathType Container) { Remove-Item -Path "$TempDirectory" -Recurse -Force } if (Test-Path -Path $TempDirectory -PathType Leaf) { $TempDirectory = [System.IO.Path]::GetDirectoryName($TempDirectory) $guidPattern = "\\[0-9a-fA-F]{8}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{4}-[0-9a-fA-F]{12}$" if ($TempDirectory -match $guidPattern) { # Removing parent directory recursively if it is a guid pattern Remove-Item -Path "$TempDirectory" -Recurse -Force } } } <# .SYNOPSIS Updates the specified text in one or multiple files using the specified encoding. .DESCRIPTION The `Update-TextInFileWithEncoding` function replaces the specified text in one or multiple files with the provided replacement text, using the specified encoding. .PARAMETER FilePath Specifies the path to the file or files in which the text should be replaced. This parameter can accept an array of strings to support multiple file paths. .PARAMETER SearchText Specifies the text to search for in the file or files. .PARAMETER ReplaceText Specifies the replacement text to use. .PARAMETER Encoding Specifies the encoding to use when reading and writing the file or files. The default encoding is UTF-8. .NOTES - The function performs a byte-level search and replace operation in the file or files. - The function uses the specified encoding when reading the file or files and writing the modified content back to the file or files. - If the search text is found in the file or files, it is replaced with the provided replacement text. - If the search text is not found in any of the files, an error is displayed. - The FilePath parameter accepts an array of strings to support multiple file paths. - The FilePath parameter is mandatory, while the SearchText and ReplaceText parameters are optional. #> function Update-TextInFileWithEncoding { param ( [Parameter(Mandatory = $true)] [string[]] $FilePath, [Parameter(Mandatory = $true)] [string] $SearchText, [Parameter(Mandatory = $true)] [string] $ReplaceText, [System.Text.Encoding] $Encoding = [System.Text.Encoding]::UTF8 ) foreach ($file in $FilePath) { $bytes = [System.IO.File]::ReadAllBytes($file) # Define the byte sequences to search for and replace. $searchBytes = $Encoding.GetBytes($SearchText) $replaceBytes = $Encoding.GetBytes($ReplaceText) # Find the position of the search bytes. $pos = IndexOfBytes $bytes $searchBytes if ($pos -ge 0) { # Replace the search bytes with the replace bytes. for ($i = 0; $i -lt $replaceBytes.Length; $i++) { $bytes[$pos + $i] = $replaceBytes[$i] } # Write the modified bytes back to the file. [System.IO.File]::WriteAllBytes($file, $bytes) } else { Write-Error "No search text found in $file" } } } <# .SYNOPSIS Replaces the requireAdministrator manifest entry with asInvoker in an application manifest file. .DESCRIPTION The `Set-AsInvoker` function replaces the `requireAdministrator` manifest entry with `asInvoker` in the specified application manifest file. It uses the `Update-TextInFileWithEncoding` function to perform the replacement. .PARAMETER FilePath Specifies the path to the application manifest file to update. .NOTES - The function performs a text-based search and replace operation in the file, using ASCII encoding. - If the `requireAdministrator` entry is found in the file, it is replaced with `asInvoker`. - If the `requireAdministrator` entry is not found, an error is displayed. #> function Set-AsInvoker { param ( [Parameter(Mandatory = $true)] [string] $FilePath ) $searchText = 'requireAdministrator"' $replaceText = 'asInvoker" ' Update-TextInFileWithEncoding -FilePath $FilePath -SearchText $searchText -ReplaceText $replaceText -Encoding ([System.Text.Encoding]::ASCII) } function Copy-Recursive2 { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] param ( [string]$Source, # The source directory to copy from [string]$Destination # The destination directory to copy to ) # Create the destination directory, if it doesn't exist New-Item -ItemType Directory -Path $Destination -Force | Out-Null # Get all items in the source directory recursively $items = Get-ChildItem $Source -Recurse for ($i = 0; $i -lt $items.Count; $i++) { $sourceItem = $items[$i] # Replace the source path with the destination in the target path $targetPath = $sourceItem.FullName -replace [regex]::Escape($Source), $Destination if (Test-Path -Path $targetPath) { $targetItem = Get-Item $targetPath } # Check if the current sourceItem is a directory if ($sourceItem.PSIsContainer) { # If it is, create the same directory structure in the destination New-Item -ItemType Directory -Path $targetPath -Force | Out-Null } else { $overwrite = $true if (Test-Path -Path $targetPath -PathType Leaf) { # If it's a file, copy it to the destination if ($sourceItem.Extension -eq ".dll" -or $sourceItem.Extension -eq ".exe" -or $sourceItem.Extension -eq ".sys" ) { $sourceVersion = (Get-Command "$($sourceItem.FullName)") $destVersion = (Get-Command "$($targetPath)") if (($sourceItem.Length -eq $targetItem.Length) -and ($sourceItem.Length -eq $targetItem.Length)) { if ($sourceVersion.FileVersionInfo.FileVersion -eq $destVersion.FileVersionInfo.FileVersion) { if ($sourceVersion.FileVersionInfo.ProductVersion -eq $destVersion.FileVersionInfo.ProductVersion) { $overwrite = $false } } } } elseif ($sourceItem.Extension -eq ".ico") { if (($sourceItem.Length -eq $targetItem.Length) -and ($sourceItem.Length -eq $targetItem.Length)) { if ($sourceItem.LastWriteTimeUtc -eq $targetItem.LastWriteTimeUtc) { $overwrite = $false } } } } if ($overwrite) { Write-Host "Copying" Write-Host "$($sourceItem.FullName)" Write-Host "$targetPath" Copy-Item $sourceItem.FullName -Destination $targetPath -Force | Out-Null } else { Write-Host "Skipping" Write-Host "$($sourceItem.FullName)" } Write-Host "" } } } function Find-FileRecursively { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] param ( [Parameter(Mandatory = $true)] [string]$DirectoryPath, [Parameter(Mandatory = $true)] [string]$FileName ) $foundFiles = Get-ChildItem -Path $DirectoryPath -Recurse -File | Where-Object { $_.Name -eq $FileName } if ($foundFiles.Count -eq 1) { $found = $foundFiles | Select-Object -First 1 -Property FullName return $found.FullName } } function Find-FileDirRecursively { [Diagnostics.CodeAnalysis.SuppressMessage("PSUseApprovedVerbs","")] param ( [Parameter(Mandatory = $true)] [string]$DirectoryPath, [Parameter(Mandatory = $true)] [string]$FileName ) $found = Find-FileRecursively -DirectoryPath $DirectoryPath -FileName $FileName $Directory = [System.IO.Path]::GetDirectoryName($found) return $Directory } |