대용량 파일 복사 중 진행률 (Copy-Item & Write-Progress?)
PowerShell에서 정말 큰 파일 (한 서버에서 다른 서버로)을 복사하고 진행 상황을 표시하는 방법이 큰 파일입니까?
많은 파일을 복사하고 진행 상황을 표시하기 위해 루핑과 함께 Write-Progress를 사용하는 솔루션이 있습니다. 그러나 단일 파일의 진행 상황을 표시하는 것을 의미합니다.
이견있는 사람?
의 진행 상황에 대해 들어 본 적이 없습니다 Copy-Item
. 외부 도구를 사용하지 않을 경우 스트림을 실험 할 수 있습니다. 버퍼의 크기는 다양하게 다른 값 (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
}
}
BitsTransfer를 사용하는 것이 훨씬 더 나은 솔루션 인 것처럼 보이지만 PowerShell 2.0 이상을 사용하는 대부분의 Windows 컴퓨터에서 OOTB가 제공되는 것입니다.
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)
cmd /c copy /z src dest
PowerShell은 PowerShell에서 순수한 실행 가능하며 진행률을 백분율로 표시합니다.
더 큰 버퍼를 사용하고 더 큰 파일에는 [long]을 사용하기 위해 stej의 코드를 수정하고 경과 시간을 추적하고 남은 시간을 추정하기 위해 System.Diagnostics.Stopwatch 클래스를 사용했습니다.
또한 전송 중 전송률보고 및 전체 경과 시간 및 전체 전송률 출력이 추가되었습니다.
4MB (4096 * 1024 바이트) 버퍼를 사용하여 Wi-Fi를 통해 NAS에서 노트북의 USB 스틱으로 복사하는 Win7 기본 처리량보다 향상됩니다.
할 일 목록 :
- 오류 처리 추가 (catch)
- get-childitem 파일 목록을 입력으로 처리
- 여러 파일을 복사 할 때 중첩 된 진행률 표시 줄 (파일 x / y, 전체 데이터가 복사 된 경우 % 등)
- 버퍼 크기에 대한 입력 변수
자유롭게 사용 / 개선하십시오 :-)
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();
}
}
내가 아는 것은 아닙니다. 어쨌든 이것에 대해 복사 항목을 사용하지 않는 것이 좋습니다. 나는 그것이 네트워크를 통해 매우 큰 파일 복사본에 대해 원하는 재 시도를 지원하기 위해 robocopy.exe처럼 견고하게 설계를 생각하지 않습니다.
이 재귀 함수는 소스 경로에서 대상 경로로 파일과 디렉토리를 재귀로 복사합니다.
대상 경로에 파일이 이미 있으면 최신 파일로만 복사합니다.
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
}
안녕하세요, Scripting Guy! 의 Sean Kearney 블로그는 내가 약속이 꽤 잘 작동합니다.
Function Copy-WithProgress
{
[CmdletBinding()]
Param
(
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$Source,
[Parameter(Mandatory=$true,
ValueFromPipelineByPropertyName=$true,
Position=0)]
$Destination
)
$Source=$Source.tolower()
$Filelist=Get-Childitem "$Source" –Recurse
$Total=$Filelist.count
$Position=0
foreach ($File in $Filelist)
{
$Filename=$File.Fullname.tolower().replace($Source,'')
$DestinationFile=($Destination+$Filename)
Write-Progress -Activity "Copying data from '$source' to '$Destination'" -Status "Copying File $Filename" -PercentComplete (($Position/$total)*100)
Copy-Item $File.FullName -Destination $DestinationFile
$Position++
}
}
그런 다음 사용하려는 비용 :
Copy-WithProgress -Source $src -Destination $dest
Trevor Sullivan이 Robocopy의 PowerShell에 Copy-ItemWithProgress 라는 명령을 추가하는 방법에 대한 글을 작성했습니다 .
오래된 주제에 부딪히는 사람이되는 것을 싫어하지만이 게시물이 매우 유용하다는 것을 알았습니다. stej의 스 니펫에 대한 성능 테스트를 실행하고 Graham Gold의 개선과 Nacht의 BITS 제안에 대해 다음과 같이 설명했습니다.
- 나는 시간 예측과 속도 판독과 함께 Graham의 명령을 정말 좋아했습니다.
- 또한 전송 방법으로 BITS를 사용하는 속도가 크게 빨라지 는 것도 정말 마음에 들었습니다.
둘 사이의 결정에 직면했습니다 ... Start-BitsTransfer가 비동기 모드를 지원한다는 것을 알았습니다. 두 가지를 합친 결과입니다.
function Copy-File {
param([string]$from, [string]$to)
try {
$job = Start-BitsTransfer -Source $from -Destination $to `
-Description "Moving: $from => $to" `
-DisplayName "Backup" -Asynchronous
# Start stopwatch
$sw = [System.Diagnostics.Stopwatch]::StartNew()
Write-Progress -Activity "Connecting..."
while ($job.JobState.ToString() -ne "Transferred") {
switch ($job.JobState.ToString()) {
"Connecting" {
break
}
"Transferring" {
$pctcomp = ($job.BytesTransferred / $job.BytesTotal) * 100
$elapsed = ($sw.elapsedmilliseconds.ToString()) / 1000
if ($elapsed -eq 0) {
$xferrate = 0.0
} else {
$xferrate = (($job.BytesTransferred / $elapsed) / 1mb);
}
if ($job.BytesTransferred % 1mb -eq 0) {
if ($pctcomp -gt 0) {
$secsleft = ((($elapsed / $pctcomp) * 100) - $elapsed)
} else {
$secsleft = 0
}
Write-Progress -Activity ("Copying file '" + ($PathName.Split("\") | Select -last 1) + "' @ " + "{0:n2}" -f $xferrate + "MB/s") `
-PercentComplete $pctcomp `
-SecondsRemaining $secsleft
}
break
}
"Transferred" {
break
}
Default {
throw $job.JobState.ToString() + " unexpected BITS state."
}
}
}
$sw.Stop()
$sw.Reset()
} finally {
Complete-BitsTransfer -BitsJob $job
Write-Progress -Activity "Completed" -Completed
}
}
참조 URL : https://stackoverflow.com/questions/2434133/progress-during-large-file-copy-copy-item-write-progress
'ProgramingTip' 카테고리의 다른 글
JSON 값 1 또는 0- 정수 또는 부울 (0) | 2020.12.31 |
---|---|
Meteor :없는 mongo 종료 코드 100 (0) | 2020.12.31 |
Parse는 얼마나 확장 가능합니까? (0) | 2020.12.31 |
django 관리자 생성 후 사이트 일치 쿼리 가져 오기 오기가 존재하지 않음 발생 오류 (0) | 2020.12.31 |
Android 날짜 선택기에서 미래 날짜를 선택하는 방법 (0) | 2020.12.31 |