large item from files delete create comando powershell xcopy copy-item

from - Powershell Copy-Item pero solo copia archivos modificados



powershell copy-item overwrite (3)

Estoy tratando de responder a través de un directorio y copiarlo de A a B. Esto se puede hacer con lo siguiente:

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

Sin embargo, quiero poder copiar solo los archivos nuevos (los que existen en src pero no dest) y también los archivos que pueden haber cambiado en base a una verificación CRC y no a una marca 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 verificación de CRC en un archivo específico ... Simplemente no estoy seguro de cómo unir los dos scripts para realmente darme lo que necesito. Tampoco sé si la verificación CRC anterior es realmente la forma correcta de hacerlo.

¿Alguien tiene alguna idea?


Ambas son respuestas sólidas para powershell, pero probablemente sería mucho más fácil simplemente aprovechar Robocopy (aplicación de copia robusta suministrada por MS).

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

Lograría lo mismo.


Encontré una solución ... pero no estoy seguro de que sea 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 } }


Estas son algunas de las pautas sobre cómo puede mantener su script para que sea más fácil de mantener.

Convierte el script original como filtro.

filter HasChanged { param($file) # if $file''s MD5 has does not exist # then return $_ }

Luego simplemente filtre todos los archivos que están actualizados 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 puedes crear otra función que genere un subdirectorio.

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