Home > front end >  Move-Item, but keep newest if conflict
Move-Item, but keep newest if conflict

Time:03-08

I got a few foreach loops, where I am doing some if and elseif's in. They're basically set to sort out a bunch of files based on their name. But I got a particular case, where there are a few files, that aparantly exist in 2 different locations. But I want to keep the newest file always.

My code looks like this

$CreoRod = "C:\Test\Creo"
$97MappeRod = "C:\Test\97"
$97Files = Get-ChildItem -File -Path $97MappeRod
$CreoRodFiles = Get-ChildItem -File -Path $CreoRod
  
foreach ($file in $97Files) {
    if ($file -like "0*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\0xxx"
    } elseif ($file -like "48*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\48xxx"
    } elseif ($file -like "49*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\49xxx"
    } elseif ($file -like "97*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\97xxx"
    } elseif ($file -like "98*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\98xxx"
    } elseif ($file -like "99*") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\99xxx"
    } elseif ($file -notmatch "config.pro") {
        Move-Item -Path "$97MappeRod\$file" -Destination "$CreoRod\Diverse"
    }
}

Is it possible to do something to make it compare with existing file, and if the existing file is newer, then delete the current. But if it is older then replace?

CodePudding user response:

I haven't tested this but it might help you with the logic, first you can use a helper function to test if a file with the same name exists in the destination and if it does exists, test if it should be replaced ($true if newer or if the destination does not have a file with that name) or remove the source file ($false).

function ShouldMove {
    param($File, $Destination)
    $testPath = Join-Path $Destination -ChildPath $File.Name
    if(Test-Path $testPath) {
        # if the destination folder contains this file name
        $destFile = Get-Item $testPath
        if($File.CreationTime -gt $destFile.CreationTime) {
            # if the source file is newer return `$true`
            return $true
        }
        # else `$false`
        return $false
    }
    # if destination does not have this file, return `$true`
    $true

}

foreach ($file in $97Files) {
    $destination = switch -Wildcard($file.Name) {
        "0*"  { "$CreoRod\0xxx" ; break }
        "48*" { "$CreoRod\48xxx"; break }
        "49*" { "$CreoRod\49xxx"; break }
        "97*" { "$CreoRod\97xxx"; break }
        "98*" { "$CreoRod\98xxx"; break }
        "99*" { "$CreoRod\99xxx"; break }
        { $_ -notmatch "config.pro" } { "$CreoRod\Diverse" }
        Default {
            Write-Warning "No condition was met, ignoring $($file.Name)"
        }
    }
    
    if(-not $destination) { continue }
    if(ShouldMove -File $file -Destination $destination) {
        # `-Force` to replace it
        Move-Item -LiteralPath $file.FullName -Destination $destination -Force
        continue
    }
    Remove-Item -LiteralPath $file.FullName
}

CodePudding user response:

I think your question is about moving file to a new destination folder if the file name meets certain conditions.
Then, if a file with that name already exists in the target destination folder, move that file only if it is newer than the existing file.

If that assumption is correct, you can do:

$CreoRod    = "C:\Test\Creo"   # destination
$97MappeRod = "C:\Test\97"     # source
$97Files     = Get-ChildItem -File -Path $97MappeRod

foreach ($file in $97Files) {
    # determine destination path
    $targetFolder = $null
    if ($file.Name -notlike '*config.pro*')          { $targetFolder = 'Diverse' }
    elseif ($file.Name -match '^(0|48|49|97|98|99)') { $targetFolder = '{0}xxx' -f $matches[1] }

    # file name was not recognized, so skip this one and proceed with the rest
    if ([string]::IsNullOrWhiteSpace($targetFolder)) { continue }

    # complete the target destination path
    $targetFolder = Join-Path -Path $CreoRod -ChildPath $targetFolder

    # try and get the file already in the targetFolder
    $existingFile = Get-Item -Path (Join-Path -Path $targetFolder -ChildPath $file.Name) -ErrorAction SilentlyContinue
    if ($existingFile) {
        # a file with that name already exists, check if the file from the source folder is newer
        $canMoveThis = ($existingFile.LastWriteTime -lt $file.LastWriteTime)
    }
    else {
        $canMoveThis = $true
        # should we create the target path if it doesn't exist yet?
        $null = New-Item -Path $targetFolder -ItemType Directory -Force
    }

    if ($canMoveThis) {
        # all clear, move the file
        $file | Move-Item -Destination $targetFolder -Force
    }
}
  • Related