Использование powershell для копирования новых и обновленных файлов

Я полный новичок, когда дело доходит до powershell, но мне дали скрипт, который мне нужно улучшить, чтобы мы могли перемещать обновленные или новые файлы с одного сервера на другой. Мне удалось разобраться с текущим скриптом, но я изо всех сил пытаюсь найти правильные командлеты и параметры для достижения желаемого поведения.

Сценарий, который у меня есть, успешно обнаруживает измененные файлы и перемещает их в место, готовое для передачи на другой сервер, но не обнаруживает новые файлы.

Может ли кто-нибудь дать мне некоторые рекомендации относительно того, как я смогу добиться обоих вариантов поведения?

$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
}

person matt_isbell    schedule 19.09.2017    source источник
comment
Если это файл сценария, я бы указал, когда вы вызываете известные параметры командлета, такие как Get-ChildItem -Path или -LiteralPath, если вы не хотите, чтобы подстановочные знаки проходили. Кроме того, в вашем предложении If ($_ вы должны использовать Continue вместо Return, чтобы он продолжал обрабатывать остальную часть конвейера. Просто некоторые наблюдения, поскольку я не понимаю вашей конечной цели. Изменился по сравнению с чем?   -  person Maximilian Burszley    schedule 19.09.2017
comment
Извините, я не думал, что был достаточно ясен. Мы хотим сравнить состояние файлов через определенный промежуток времени. Это будет использоваться для перемещения новых файлов обновлений или измененных файлов обновлений. Таким образом, скрипт должен обнаруживать новые файлы в «текущем каталоге» по сравнению с «предыдущим каталогом», а также любые изменения в файлах в «текущем» по сравнению с «предыдущим», затем эти файлы необходимо скопировать во временную папку. каталог дельта. Это немного яснее?   -  person matt_isbell    schedule 19.09.2017
comment
Итак, файлы, с которыми вы проводите сравнение, каким-то образом дублируются? Вы просматриваете только что обновленные файлы или новые файлы тоже?   -  person Maximilian Burszley    schedule 19.09.2017
comment
Мы сравниваем файлы в «текущем» с файлами в «предыдущем». Мы хотим знать, когда в «текущем» есть новый файл, путем сравнения, показывающего, что в «предыдущем» нет соответствующего файла. Затем мы также хотим просмотреть отметку времени последней записи, чтобы определить, изменился ли файл. После того, как скрипт получит удовольствие, последней задачей будет копирование новых и обновленных файлов как в «дельта», так и в «предыдущий» каталог, чтобы «предыдущий» и «текущий» совпадали.   -  person matt_isbell    schedule 19.09.2017
comment
Теперь я понимаю вашу проблему. Дайте мне несколько, и я опубликую ответ для вас.   -  person Maximilian Burszley    schedule 19.09.2017
comment
Честно говоря, я бы не стал использовать для этого PowerShell. Я бы использовал robocopy или, если вы действительно, действительно по какой-то причине нужно отслеживать перемещение файлов, просто поместите файлы в систему контроля версий и управляйте ими таким образом. Не изобретайте велосипед.   -  person Bacon Bits    schedule 19.09.2017


Ответы (1)


Вот упрощенный подход к вашим потребностям. Следует отметить, что некоторые конструкции, которые я использовал, требуют 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
person Maximilian Burszley    schedule 19.09.2017
comment
Спасибо за это. Кажется, это работает, однако теперь я сталкиваюсь с проблемой, из-за которой я получаю следующий вывод: Невозможно преобразовать значение System.Object[] типа System.Object[] в тип System.DateTime. Это как-то связано со строкой If ($File.LastWriteTime..., и я совершенно не понимаю, почему она не может выполнить преобразование. - person matt_isbell; 29.09.2017
comment
@matt_isbell, что, вероятно, означает, что вы сталкиваетесь с повторяющимися базовыми именами и пытаетесь выполнить групповое сравнение - person Maximilian Burszley; 30.09.2017
comment
Хм, а базовое имя включает расширение файла? Файлы, которые мы пытаемся переместить, являются файлами обновления AV, поэтому вполне могут быть одинаковые имена файлов, но разные расширения. - person matt_isbell; 02.10.2017
comment
@matt_isbell Верно. .Name включает расширения, как я упоминал в ответе. - person Maximilian Burszley; 02.10.2017
comment
О да! Это научит меня читать все!!! Извиняюсь. Спасибо за вашу помощь. - person matt_isbell; 04.10.2017