2009-03-24 20 views
23

Sto cercando di ricorsivamente attraverso una directory e copiarlo da A a B. che può essere fatto con il seguente:PowerShell Copy-Item, ma solo copiare i file modificati

Copy-Item C:\MyTest C:\MyTest2 –recurse 

Voglio essere in grado però di copia solo nuovi file (quelli che esistono in src ma non in destinazione) e copiano anche solo i file che possono essere cambiati in base a un controllo CRC e non a un timestamp.

$file = "c:\scripts" 
param 
(
$file 
) 

$algo = [System.Security.Cryptography.HashAlgorithm]::Create("MD5") 
$stream = New-Object System.IO.FileStream($file, [System.IO.FileMode]::Open) 

$md5StringBuilder = New-Object System.Text.StringBuilder 
$algo.ComputeHash($stream) | ` 
% { [void] $md5StringBuilder.Append($_.ToString("x2")) } 
$md5StringBuilder.ToString() 

$stream.Dispose() 

Questo codice mi dà un controllo CRC su un file specifico ... io sono solo non è sicuro come mettere insieme i due script di darmi davvero quello che mi serve. Inoltre, non so se il controllo CRC sopra è in realtà il modo corretto di farlo.

Qualcuno ha qualche idea?

+7

La mia prima domanda sarebbe stata quella di usare Robocopy? Stai davvero reinventando una ruota molto ben progettata qui. – EBGreen

risposta

3

ho trovato una soluzione ... ma non sono sicuro che è la migliore dal punto di vista delle prestazioni:

$Source = "c:\scripts" 
$Destination = "c:\test" 
################################################### 
################################################### 
Param($Source,$Destination) 
function Get-FileMD5 { 
    Param([string]$file) 
    $mode = [System.IO.FileMode]("open") 
    $access = [System.IO.FileAccess]("Read") 
    $md5 = New-Object System.Security.Cryptography.MD5CryptoServiceProvider 
    $fs = New-Object System.IO.FileStream($file,$mode,$access) 
    $Hash = $md5.ComputeHash($fs) 
    $fs.Close() 
    [string]$Hash = $Hash 
    Return $Hash 
} 
function Copy-LatestFile{ 
    Param($File1,$File2,[switch]$whatif) 
    $File1Date = get-Item $File1 | foreach-Object{$_.LastWriteTimeUTC} 
    $File2Date = get-Item $File2 | foreach-Object{$_.LastWriteTimeUTC} 
    if($File1Date -gt $File2Date) 
    { 
     Write-Host "$File1 is Newer... Copying..." 
     if($whatif){Copy-Item -path $File1 -dest $File2 -force -whatif} 
     else{Copy-Item -path $File1 -dest $File2 -force} 
    } 
    else 
    { 
     #Don't want to copy this in my case..but good to know 
     #Write-Host "$File2 is Newer... Copying..." 
     #if($whatif){Copy-Item -path $File2 -dest $File1 -force -whatif} 
     #else{Copy-Item -path $File2 -dest $File1 -force} 
    } 
    Write-Host 
} 

# Getting Files/Folders from Source and Destination 
$SrcEntries = Get-ChildItem $Source -Recurse 
$DesEntries = Get-ChildItem $Destination -Recurse 

# Parsing the folders and Files from Collections 
$Srcfolders = $SrcEntries | Where-Object{$_.PSIsContainer} 
$SrcFiles = $SrcEntries | Where-Object{!$_.PSIsContainer} 
$Desfolders = $DesEntries | Where-Object{$_.PSIsContainer} 
$DesFiles = $DesEntries | Where-Object{!$_.PSIsContainer} 

# Checking for Folders that are in Source, but not in Destination 
foreach($folder in $Srcfolders) 
{ 
    $SrcFolderPath = $source -replace "\\","\\" -replace "\:","\:" 
    $DesFolder = $folder.Fullname -replace $SrcFolderPath,$Destination 
    if(!(test-path $DesFolder)) 
    { 
     Write-Host "Folder $DesFolder Missing. Creating it!" 
     new-Item $DesFolder -type Directory | out-Null 
    } 
} 

# Checking for Folders that are in Destinatino, but not in Source 
foreach($folder in $Desfolders) 
{ 
    $DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:" 
    $SrcFolder = $folder.Fullname -replace $DesFilePath,$Source 
    if(!(test-path $SrcFolder)) 
    { 
     Write-Host "Folder $SrcFolder Missing. Creating it!" 
     new-Item $SrcFolder -type Directory | out-Null 
    } 
} 

# Checking for Files that are in the Source, but not in Destination 
foreach($entry in $SrcFiles) 
{ 
    $SrcFullname = $entry.fullname 
    $SrcName = $entry.Name 
    $SrcFilePath = $Source -replace "\\","\\" -replace "\:","\:" 
    $DesFile = $SrcFullname -replace $SrcFilePath,$Destination 
    if(test-Path $Desfile) 
    { 
     $SrcMD5 = Get-FileMD5 $SrcFullname 
     $DesMD5 = Get-FileMD5 $DesFile 
     If(Compare-Object $srcMD5 $desMD5) 
     { 
      Write-Host "The Files MD5's are Different... Checking Write 
      Dates" 
      Write-Host $SrcMD5 
      Write-Host $DesMD5 
      Copy-LatestFile $SrcFullname $DesFile 
     } 
    } 
    else 
    { 
     Write-Host "$Desfile Missing... Copying from $SrcFullname" 
     copy-Item -path $SrcFullName -dest $DesFile -force 
    } 
} 

# Checking for Files that are in the Destinatino, but not in Source 
foreach($entry in $DesFiles) 
{ 
    $DesFullname = $entry.fullname 
    $DesName = $entry.Name 
    $DesFilePath = $Destination -replace "\\","\\" -replace "\:","\:" 
    $SrcFile = $DesFullname -replace $DesFilePath,$Source 
    if(!(test-Path $SrcFile)) 
    { 
     Write-Host "$SrcFile Missing... Copying from $DesFullname" 
     copy-Item -path $DesFullname -dest $SrcFile -force 
    } 
} 
7

Ecco alcune delle linee guida come è possibile lo script per essere più gestibile.

Converte lo script originale come filtro.

filter HasChanged { 
    param($file) 

    # if $file's MD5 has does not exist 
    # then return $_ 
} 

Quindi, è sufficiente filtrare tutti i file che vengono aggiornati e copiarli.

# Note that "Copy-Item" here does not preserve original directory structure 
# Every updated file gets copied right under "C:\MyTest2" 
ls C:\MyTest -Recurse | HasChanged | Copy-Item -Path {$_} C:\MyTest2 

Oppure è possibile creare un'altra funzione che genera sottodirectory

ls C:\MyTest -Recurse | HasChanged | % { Copy-Item $_ GenerateSubDirectory(...) } 
22

Entrambe queste sono risposte concrete per PowerShell, ma sarebbe probabilmente molto più facile da solo leva Robocopy (MS Fornito robusta copia l'applicazione).

robocopy "C:\SourceDir\" "C:\DestDir\" /MIR 

farebbe la stessa cosa.

+7

robocopy non confronta il contenuto per quanto ne so. Si basa su dimensioni e timbri data. – bart

Problemi correlati