Я внес изменения в код из stej (который был большим, только то, что мне нужно!) Использовать больший буфер, [длинный ] для больших файлов и используется класс System.Diagnostics.Stopwatch для отслеживания прошедшего времени и оценки оставшегося времени.
Также добавлено сообщение о скорости передачи при передаче и выводе общего истекшего времени и общей скорости передачи.
Использование буфера 4 МБ (4096 * 1024 байт), чтобы стать лучше, чем собственное копирование пропускной способности Win7 с NAS на USB-накопитель на ноутбуке через Wi-Fi.
На To-Do список:
- добавить обработку ошибок (вылов)
- обрабатывать Get-ChildItem списка файлов в качестве входных данных
- вложенных полос прогресса при копировании нескольких файлов (файл х у,% если итоговые данные копируются и т.д.) параметр
- ввода для размера буфера
Вы можете использовать/улучшить :-)
function Copy-File {
param([string]$from, [string]$to)
$ffile = [io.file]::OpenRead($from)
$tofile = [io.file]::OpenWrite($to)
Write-Progress `
-Activity "Copying file" `
-status ($from.Split("\")|select -last 1) `
-PercentComplete 0
try {
$sw = [System.Diagnostics.Stopwatch]::StartNew();
[byte[]]$buff = new-object byte[] (4096*1024)
[long]$total = [long]$count = 0
do {
$count = $ffile.Read($buff, 0, $buff.Length)
$tofile.Write($buff, 0, $count)
$total += $count
[int]$pctcomp = ([int]($total/$ffile.Length* 100));
[int]$secselapsed = [int]($sw.elapsedmilliseconds.ToString())/1000;
if ($secselapsed -ne 0) {
[single]$xferrate = (($total/$secselapsed)/1mb);
} else {
[single]$xferrate = 0.0
}
if ($total % 1mb -eq 0) {
if($pctcomp -gt 0)`
{[int]$secsleft = ((($secselapsed/$pctcomp)* 100)-$secselapsed);
} else {
[int]$secsleft = 0};
Write-Progress `
-Activity ($pctcomp.ToString() + "% Copying file @ " + "{0:n2}" -f $xferrate + " MB/s")`
-status ($from.Split("\")|select -last 1) `
-PercentComplete $pctcomp `
-SecondsRemaining $secsleft;
}
} while ($count -gt 0)
$sw.Stop();
$sw.Reset();
}
finally {
write-host (($from.Split("\")|select -last 1) + `
" copied in " + $secselapsed + " seconds at " + `
"{0:n2}" -f [int](($ffile.length/$secselapsed)/1mb) + " MB/s.");
$ffile.Close();
$tofile.Close();
}
}
Интересное решение. Когда я попробовал это, я получил ошибку - Не удалось преобразовать значение «2147483648», чтобы ввести «System.Int32». Ошибка: «Значение было слишком большим или слишком маленьким для Int32». После замены [int] на [long], он отлично работал. Thanks –
Это значит, что вы копируете файлы размером более 2 ГБ? Полагаю, что так. Я рад, что это работает :) – stej
+1, хорошее решение – Remko