Powershell moving files but backup the files before replacing

This topic contains 3 replies, has 2 voices, and was last updated by Profile photo of Dave Wyatt Dave Wyatt 3 years, 8 months ago.

  • Author
    Posts
  • #10468
    Profile photo of Ahmar Zia
    Ahmar Zia
    Participant

    I have three directories: 1. RFC 2. Source 3. Backup

    RFC contains files and folders(that contain files) that I need to replace in the source folder but before I replace/move files I need to backup the files I'm replacing from source to the backup folder.

    I have wrote the following code, which compares RFC and Source and copies the files to backup, but it doesn't copy sub directories. I want it to move files within the sub directories as well with the same folder structure as Source. And once the copy of the files is done. I want to move files from RFC to Source.

    Please any help would be highly appreciated.

    $source = "C:\Scripts\Source\"
    $backup = "C:\Scripts\Destination\"
    $rfc_dir = "C:\Scripts\RFC000001234\"

    $folder1Files= dir $source
    $folder2Files= dir $rfc_dir

    compare-object $folder1Files $folder2Files -property name -includeEqual -excludeDifferent | ForEach-object {
    copy-item "$source\$($_.name)" -Destination "$backup" -Force -recurse
    }

  • #10471
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    I haven't tested this, but if your above code is working, you can probably just add a -Recurse switch to both of these lines:

    $folder1Files= dir $source -Recurse
    $folder2Files= dir $rfc_dir -Recurse
    
  • #10473
    Profile photo of Ahmar Zia
    Ahmar Zia
    Participant

    When I run the following:
    $source = "C:\Users\x326269\Documents\Scripts\Source\"
    $target = "C:\Users\x326269\Documents\Scripts\Destination\"
    $rfc_dir = "C:\Users\x326269\Documents\Scripts\RFC000001234\"

    $folder1Files= dir $source -Recurse
    $folder2Files= dir $rfc_dir -Recurse

    compare-object $folder1Files $folder2Files -property name -includeEqual -excludeDifferent | ForEach-object {
    copy-item "$source/$($_.name)" -Destination "$target" -Force
    }

    I'm getting the following error:
    Image and video hosting by TinyPic

  • #10474
    Profile photo of Dave Wyatt
    Dave Wyatt
    Moderator

    Sorry about that, should have looked at the code a bit closer before replying. I can think of a couple different ways to address this. You could either write a recursive function, or do a little bit of string manipulation to convert between relative and absolute paths; relative for comparing the folder contents, and absolute for the copy operation. Both should work; I went with the latter in this example. Give it a try:

    function Add-RelativePath
    {
        [CmdletBinding()]
        param (
            [Parameter(Mandatory = $true, ValueFromPipeline = $true)]
            [System.IO.FileInfo[]]
            $File,
    
            [Parameter(Mandatory = $true)]
            [System.String]
            $RootPath
        )
    
        process
        {
            foreach ($fileInfo in $File)
            {
                $params = @{
                    InputObject = $fileInfo
                    MemberType = 'NoteProperty'
                    Name = 'RelativePath'
                    Value = $fileInfo.FullName -replace "^$([regex]::Escape($RootPath))"
                }
    
                Add-Member @params -PassThru
            }
        }
    }
    
    $source = "C:\Users\x326269\Documents\Scripts\Source\"
    $target = "C:\Users\x326269\Documents\Scripts\Destination\"
    $rfc_dir = "C:\Users\x326269\Documents\Scripts\RFC000001234\"
    
    $folder1Files = Get-ChildItem -Path $source -Recurse |
    Where-Object { -not $_.PSIsContainer } |
    Add-RelativePath -RootPath $source
    
    $folder2Files = Get-ChildItem -Path $rfc_dir -Recurse |
    Where-Object { -not $_.PSIsContainer } |
    Add-RelativePath -RootPath $rfc_dir
    
    Compare-Object $folder1Files $folder2Files -Property RelativePath -IncludeEqual -ExcludeDifferent |
    ForEach-Object {
        $sourcePath = Join-Path -Path $source -ChildPath $_.RelativePath
        $destPath = Join-Path -Path $target -ChildPath $_.RelativePath
    
        $destFolder = Split-Path -Path $destPath -Parent
    
        if (-not (Test-Path -Path $destFolder -PathType Container))
        {
            $null = New-Item -Path $destFolder -ItemType Directory
        }
    
        Copy-Item -Path $sourcePath -Destination $destPath -Force
    }
    
    

    Note: I wrote this to be PowerShell 2.0-compatible, since I wasn't sure what version you are running. You can get rid of the Where-Object calls and use the -File switch on Get-ChidlItem, if you're running PowerShell 3.0 and prefer it that way.

You must be logged in to reply to this topic.