2009-03-24 49 views
23

que estoy tratando de recursivo a través de un directorio y copiarlo de A a B. Esto se puede hacer con lo siguiente:Powershell Copy-Item pero sólo copiar los archivos modificados

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

Quiero ser capaz de pesar a solo copie los archivos nuevos (que existen en src pero no en el disco) y también solo copie los archivos que pueden haber cambiado basándose en una verificación de CRC y no en un sello de fecha y hora.

$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() 

Este código me da una comprobación CRC en un archivo específico ... Soy simplemente no está seguro cómo poner los dos guiones juntos para darme realmente lo que necesito. Tampoco sé si la verificación del CRC anterior es en realidad la forma correcta de hacerlo.

¿Alguien tiene alguna idea?

+7

Mi primera pregunta sería ¿has mirado simplemente usando Robocopy? Realmente estás reinventando una rueda muy bien diseñada aquí. – EBGreen

Respuesta

3

he encontrado una solución ... pero no estoy seguro que es la mejor desde una perspectiva de rendimiento:

$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

Aquí es algunas de las pautas de cómo puede la secuencia de comandos a ser más fácil de mantener.

Conver la secuencia de comandos original como un filtro.

filter HasChanged { 
    param($file) 

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

Luego, simplemente filtre todos los archivos que se actualizan y cópielos.

# 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 

O bien, puede crear otra función que genera sub directorio

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

Ambos son respuestas sólidas para PowerShell, pero probablemente sería mucho más fácil simplemente apalancamiento Robocopy (MS suministra robusta copia de la aplicación).

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

lograrían lo mismo.

+7

robocopy no compara el contenido hasta donde yo sé. Se basa en tamaños y sellos de fecha. – bart

Cuestiones relacionadas