Created
December 20, 2023 01:54
-
-
Save IMJLA/16cdd97c7e7bc337176a5f0896c51803 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
function Copy-File { | |
param( | |
#Path to the source file | |
[Parameter( | |
Mandatory = $True, | |
Position = 0 | |
)] | |
[String]$SourceFilePath, | |
#Path to the destination file | |
[Parameter( | |
Mandatory = $True, | |
Position = 1 | |
)] | |
[String]$DestinationFilePath | |
) | |
process{ | |
# Get the file name. | |
$SourceFileName = $SourceFilePath.Split("\") | Select-Object -Last 1 | |
# Open the source and destination files. | |
$Pref = $ErrorActionPreference | |
$ErrorActionPreference = 'Stop' | |
$SourceFile = [System.IO.File]::OpenRead($SourceFilePath) | |
$DestinationFile = [System.IO.File]::OpenWrite($DestinationFilePath) | |
$ErrorActionPreference = $Pref | |
# Show a progress bar. | |
$Progress = @{ | |
Activity = "Copying file" | |
Status = $SourceFileName | |
PercentComplete = 0 | |
} | |
Write-Progress @Progress | |
try { | |
# Start a timer | |
$Stopwatch = [System.Diagnostics.Stopwatch]::StartNew() | |
# Create a 4 MiB buffer. | |
$Buffer = New-Object -TypeName Byte[] (4194304) | |
# Initialize counters to track progress based on the number of bytes written. | |
[Long]$CurrentByteCount = 0 | |
[Long]$TotalBytesRead = 0 | |
do { | |
# Read 4 MiB from the source file into the buffer. | |
$CurrentByteCount = $SourceFile.Read($Buffer, 0, $Buffer.Length) | |
# Write the buffer to the destination file. | |
$DestinationFile.Write($Buffer, 0, $CurrentByteCount) | |
# Update the counters to track progress | |
[Int64]$MillisecondsElapsed = $Stopwatch.ElapsedMilliseconds | |
[Int64]$SecondsElapsed = $MillisecondsElapsed/1000 | |
$TotalBytesRead += $CurrentByteCount | |
if ( $MillisecondsElapsed -ne 0 ) { | |
[Int64]$BytesPerMillisecond = $TotalBytesRead / $MillisecondsElapsed | |
} | |
else { | |
[Int64]$BytesPerMillisecond = 0 | |
} | |
#Update the progress bar every MiB | |
if ($TotalBytesRead % 1048576 -eq 0) { | |
[Int16]$PercentComplete = $TotalBytesRead / $SourceFile.Length * 100 | |
if($PercentComplete -gt 0){ | |
[int]$EstimatedSecondsRemaining = $SecondsElapsed / $PercentComplete * 100 - $SecondsElapsed | |
} | |
else { | |
[int]$EstimatedSecondsRemaining = 0 | |
} | |
$CopySpeed = '{0:N2}' -f ($BytesPerMillisecond*1000/1048576) | |
$Elapsed = New-TimeSpan -Seconds $SecondsElapsed | |
$Progress = @{ | |
Activity = "Copying file" | |
Status = "$PercentComplete% copying '$SourceFileName' @ $CopySpeed MiB/s. Elapsed: $Elapsed" | |
PercentComplete = $PercentComplete | |
SecondsRemaining = $EstimatedSecondsRemaining | |
} | |
Write-Progress @Progress | |
} | |
} | |
# Loop until the end of the FileStream is reached and 0 bytes are read into the buffer. | |
while ($CurrentByteCount -gt 0) | |
} | |
finally { | |
if ( $MillisecondsElapsed -ne 0 ) { | |
[Int64]$AverageBytesPerMillisecond = $SourceFile.Length/$MillisecondsElapsed | |
Write-Verbose "$SourceFileName ($($SourceFile.Length) B) copied in $($MillisecondsElapsed) Milliseconds at $AverageBytesPerMillisecond B/ms." | |
} | |
else { | |
[Int64]$AverageBytesPerMillisecond = 0 | |
} | |
#Reset the timer. | |
$Stopwatch.Reset() | |
$AmountCopied = '{0:N2}' -f ($SourceFile.Length/1048576) | |
$CopySpeed = '{0:N2}' -f ($AverageBytesPerMillisecond*1000/1048576) | |
Write-Host "$SourceFileName ($AmountCopied MiB) copied in $SecondsElapsed seconds at $CopySpeed MiB/s." | |
#Close the Source and Destination Files | |
$SourceFile.Close() | |
$DestinationFile.Close() | |
} | |
Write-Progress -Activity "Copying file" -Completed | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment