使用powershell复制新的和更新的文件

使用powershell复制新的和更新的文件,powershell,delta,Powershell,Delta,谈到powershell,我是一个完全的新手,但我得到了一个需要改进的脚本,以便我们可以将更新或新文件从一台服务器移动到另一台服务器。我已经设法掌握了当前的脚本,但正在努力找到正确的cmdlet和参数以实现所需的行为 我的脚本成功地检测到更改的文件,并将它们移动到准备传输到另一台服务器的位置,但它没有检测到任何新文件 有谁能给我一些指导,告诉我如何才能做到这两种行为 $CurrentLocation = "C:\current" $PreviousLocation = "C:\prev" $De

谈到powershell,我是一个完全的新手,但我得到了一个需要改进的脚本,以便我们可以将更新或新文件从一台服务器移动到另一台服务器。我已经设法掌握了当前的脚本,但正在努力找到正确的cmdlet和参数以实现所需的行为

我的脚本成功地检测到更改的文件,并将它们移动到准备传输到另一台服务器的位置,但它没有检测到任何新文件

有谁能给我一些指导,告诉我如何才能做到这两种行为

$CurrentLocation = "C:\current"
$PreviousLocation = "C:\prev"
$DeltaLocation = "C:\delta"

$source = @{}

#
# Get the Current Location file information
#
Get-ChildItem -recurse $CurrentLocation | Foreach-Object {
    if ($_.PSIsContainer) { return }
    $source.Add($_.FullName.Replace($CurrentLocation, ""), $_.LastWriteTime.ToString())
}
Write-Host "Content of Source"
$source

$changesDelta = @{}
$changesPrevious = @{}

#
# Get the Previous Directory contents and compare the dates against the Current Directory contents 
#
Get-ChildItem -recurse $PreviousLocation | Foreach-Object {
    if ($_.PSIsContainer) { return }
    $File = $_.FullName.Replace($PreviousLocation, "")
    if ($source.ContainsKey($File)) {
        if ($source.Get_Item($File) -ne $_.LastWriteTime.ToString()) {
            $changesDelta.Add($CurrentLocation+$File, $DeltaLocation+$File)
            $changesPrevious.Add($CurrentLocation+$File, $PreviousLocation+$File)
        }
    }
}
Write-Host "Content of changesDelta:"
$changesDelta
Write-Host "Content of changesPrevious:"
$changesPrevious

#
# Copy the files into a temporary directory
#
foreach ($key in $changesDelta.Keys) {
    New-Item -ItemType File -Path $changesDelta.Get_Item($key) -Force
    Copy-Item $key $changesDelta.Get_Item($key) -Force
}
Write-Host $changesDelta.Count "Files copied to" $DeltaLocation

#
# Copy the files into the Previous Location to match the Current Location
#
foreach ($key in $changesPrevious.Keys) {
    Copy-Item $key $changesDelta.Get_Item($key) -Force
}

这里有一个简单的方法来满足您的需求。需要注意的是,我使用的一些构造需要
PSv3
+。这不会复制目录结构,只复制文件。此外,它还比较了基名(忽略扩展名),这些基名可能会做您想要做的事情,也可能不会做您想要做的事情。可以使用
.Name
而不是
.BaseName
来扩展它以包括扩展

#requires -Version 3

$CurrentLocation  = 'C:\current'
$PreviousLocation = 'C:\prev'
$DeltaLocation    = 'C:\delta'

$Current  = Get-ChildItem -LiteralPath $CurrentLocation -Recurse -File
$Previous = Get-ChildItem -LiteralPath $PreviousLocation -Recurse -File

ForEach ($File in $Current)
{
    If ($File.BaseName -in $Previous.BaseName)
    {
        If ($File.LastWriteTime -gt ($Previous | Where-Object { $_.BaseName -eq $File.BaseName }).LastWriteTime)
        {
            Write-Output "File has been updated: $($File.FullName)"
            Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
        }
    }
    Else
    {
        Write-Output "New file detected: $($File.FullName)"
        Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
    }
}

Copy-Item -Path "$DeltaLocation\*" -Destination $PreviousLocation -Force

这里有一个简单的方法来满足您的需求。需要注意的是,我使用的一些构造需要
PSv3
+。这不会复制目录结构,只复制文件。此外,它还比较了基名(忽略扩展名),这些基名可能会做您想要做的事情,也可能不会做您想要做的事情。可以使用
.Name
而不是
.BaseName
来扩展它以包括扩展

#requires -Version 3

$CurrentLocation  = 'C:\current'
$PreviousLocation = 'C:\prev'
$DeltaLocation    = 'C:\delta'

$Current  = Get-ChildItem -LiteralPath $CurrentLocation -Recurse -File
$Previous = Get-ChildItem -LiteralPath $PreviousLocation -Recurse -File

ForEach ($File in $Current)
{
    If ($File.BaseName -in $Previous.BaseName)
    {
        If ($File.LastWriteTime -gt ($Previous | Where-Object { $_.BaseName -eq $File.BaseName }).LastWriteTime)
        {
            Write-Output "File has been updated: $($File.FullName)"
            Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
        }
    }
    Else
    {
        Write-Output "New file detected: $($File.FullName)"
        Copy-Item -LiteralPath $File.FullName -Destination $DeltaLocation
    }
}

Copy-Item -Path "$DeltaLocation\*" -Destination $PreviousLocation -Force


如果这是一个脚本文件,则在调用已知的cmdlet参数时,我会明确表示,例如
Get ChildItem-Path
-LiteralPath
,如果您不希望通配符通过。此外,在
中,如果($)
子句,您应该使用
Continue
而不是
Return
,这样它仍然处理管道的其余部分。只是一些观察,因为我不理解您的最终目标。与什么相比发生了更改?抱歉,我认为我不够清楚。我们希望在一段时间后比较文件的状态。这将e用于移动新的更新文件或更改的更新文件。因此,脚本需要检测“当前目录”中的新文件与“以前的目录”相比,以及“当前”中的文件与“以前”相比的任何更改,然后需要将这些文件复制到临时的“增量”目录。这是否更清楚一些?重复的文件也是如此您正在以某种方式与之进行比较?您是只查看更新的文件,还是查看新文件?我们正在将“当前”中的文件与“以前”中的文件进行比较。通过比较显示“以前”中没有相应的文件,我们想知道“当前”中何时有新文件。然后我们还想查看最后一个write time time Stamp以确定文件是否已更改。一旦脚本变得有趣,最后的任务将是将新文件和更新文件复制到“delta”目录和“previous”目录中,以便“previous”和“current”匹配。现在我了解您的问题。给我一些,我将为您发布答案。如果这是脚本le,如果您不希望通配符通过,则在调用已知cmdlet参数时,如
Get ChildItem-Path
-LiteralPath
时,我会显式使用。此外,在
中,如果($)
子句,您应该使用
Continue
而不是
Return
,这样它仍然处理管道的其余部分。只是一些观察,因为我不理解您的最终目标。与什么相比发生了更改?抱歉,我认为我不够清楚。我们希望在一段时间后比较文件的状态。这将e用于移动新的更新文件或更改的更新文件。因此,脚本需要检测“当前目录”中的新文件与“以前的目录”相比,以及“当前”中的文件与“以前”相比的任何更改,然后需要将这些文件复制到临时的“增量”目录。这是否更清楚一些?重复的文件也是如此您正在以某种方式与之进行比较?您是只查看更新的文件,还是查看新文件?我们正在将“当前”中的文件与“以前”中的文件进行比较。通过比较显示“以前”中没有相应的文件,我们想知道“当前”中何时有新文件。然后我们还想查看最后一个write time time Stamp以确定文件是否已更改。一旦脚本变得有趣,最后的任务将是将新文件和更新文件复制到“delta”目录和“previous”目录中,以便“previous”和“current”匹配。现在我理解了您的问题。给我一些,我将为您发布一个答案。感谢您的帮助。这是非常有用的ems来完成这项工作,但是我现在遇到了一个问题,我得到了以下输出:“无法将类型为”System.Object[]”的“System.Object[]”值转换为类型为“System.DateTime”。“这与If有关。”($File.LastWriteTime…line,我完全不知道它为什么不能进行转换。@matt_isbell这可能意味着你遇到了重复的基本名称,它正在尝试进行组比较。嗯,基本名称是否包括文件扩展名?我们尝试移动的文件是AV更新文件,因此可能有相同的文件名,但d不同的扩展。@matt_isbell Correct.
.Name
包括我在回答中提到的扩展。啊,是的!这将教会我阅读整个内容!!!抱歉。谢谢你的帮助。谢谢。它似乎可以完成工作,但我现在遇到了一个问题,我得到了以下输出:“无法转换”System.Object[]类型为“System.Object[]”的值,以键入“System.DateTime”。“这与If有关。”($File.LastWriteTime…line,我完全不知道它为什么不能进行转换。@matt_isbell这可能意味着你遇到了重复的基名称,它试图进行组比较。嗯,基名称是否包括文件扩展名?我们需要的文件