大文件复制期间的进度(Copy-Item&Write-Progress?)

有没有办法在PowerShell中复制一个真正的大文件(从一台服务器到另一台服务器),并显示其进度?

有一些解决scheme可以使用Write-Progress和循环来复制许多文件并显示进度。 但是,我似乎无法find任何可以显示单个文件的进度。

有什么想法吗?

我还没有听说Copy-Item进展。 如果你不想使用任何外部工具,你可以尝试stream。 缓冲区的大小各不相同,您可以尝试不同的值(从2kb到64kb)。

 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 -> $to" -PercentComplete 0 try { [byte[]]$buff = new-object byte[] 4096 [int]$total = [int]$count = 0 do { $count = $ffile.Read($buff, 0, $buff.Length) $tofile.Write($buff, 0, $count) $total += $count if ($total % 1mb -eq 0) { Write-Progress -Activity "Copying file" -status "$from -> $to" ` -PercentComplete ([int]($total/$ffile.Length* 100)) } } while ($count -gt 0) } finally { $ffile.Dispose() $tofile.Dispose() Write-Progress -Activity "Copying file" -Status "Ready" -Completed } } 

这似乎是一个更好的解决scheme,只是使用BitsTransfer,它似乎来OOTB大多数与Windows PowerShell 2.0或更高版本的机器。

 Import-Module BitsTransfer Start-BitsTransfer -Source $Source -Destination $Destination -Description "Backup" -DisplayName "Backup" 

另外这个选项使用本地窗口进度条…

 $FOF_CREATEPROGRESSDLG = "&H0&" $objShell = New-Object -ComObject "Shell.Application" $objFolder = $objShell.NameSpace($DestLocation) $objFolder.CopyHere($srcFile, $FOF_CREATEPROGRESSDLG) 

我修改了stej的代码(这很好,只是我需要!)使用更大的缓冲区,[长]为较大的文件,并使用System.Diagnostics.Stopwatch类追踪经过的时间和估计剩余时间。

还增加了传输过程中传输速率的报告,输出总体传输时间和传输速率。

使用4MB(4096 * 1024字节)缓冲区来获得比Win7本地吞吐量更好的从NAS复制到笔记本电脑上的USB存储棒。

在待办事项列表中:

  • 添加error handling(catch)
  • 处理get-childitem文件列表作为input
  • 复制多个文件时的嵌套进度条(y的文件x,复制数据的总数等)
  • input缓冲区大小的参数

随意使用/改进:-)

 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(); } } 

不是我所知道的。 我不会推荐使用复制项目。 我不认为它已被devise为强大的像robocopy.exe支持重试,你会想在networking上的超大型文件副本。

 cmd /c copy /z src dest 

不是纯粹的PowerShell,而是在PowerShell中执行,并以百分比显示进度

此recursion函数将文件和目录从源pathrecursion复制到目标path

如果文件已经存在于目标path上,则仅使用较新的文件复制文件。

 Function Copy-FilesBitsTransfer( [Parameter(Mandatory=$true)][String]$sourcePath, [Parameter(Mandatory=$true)][String]$destinationPath, [Parameter(Mandatory=$false)][bool]$createRootDirectory = $true) { $item = Get-Item $sourcePath $itemName = Split-Path $sourcePath -leaf if (!$item.PSIsContainer){ #Item Is a file $clientFileTime = Get-Item $sourcePath | select LastWriteTime -ExpandProperty LastWriteTime if (!(Test-Path -Path $destinationPath\$itemName)){ Start-BitsTransfer -Source $sourcePath -Destination $destinationPath -Description "$sourcePath >> $destinationPath" -DisplayName "Copy Template file" -Confirm:$false if (!$?){ return $false } } else{ $serverFileTime = Get-Item $destinationPath\$itemName | select LastWriteTime -ExpandProperty LastWriteTime if ($serverFileTime -lt $clientFileTime) { Start-BitsTransfer -Source $sourcePath -Destination $destinationPath -Description "$sourcePath >> $destinationPath" -DisplayName "Copy Template file" -Confirm:$false if (!$?){ return $false } } } } else{ #Item Is a directory if ($createRootDirectory){ $destinationPath = "$destinationPath\$itemName" if (!(Test-Path -Path $destinationPath -PathType Container)){ if (Test-Path -Path $destinationPath -PathType Leaf){ #In case item is a file, delete it. Remove-Item -Path $destinationPath } New-Item -ItemType Directory $destinationPath | Out-Null if (!$?){ return $false } } } Foreach ($fileOrDirectory in (Get-Item -Path "$sourcePath\*")) { $status = Copy-FilesBitsTransfer $fileOrDirectory $destinationPath $true if (!$status){ return $false } } } return $true } 

Trevor Sullivan撰写了关于如何在Robocopy上添加一个名为Copy-ItemWithProgress的命令给Powershell的文章。

Interesting Posts