Author Posts

October 2, 2013 at 7:36 am

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
}

October 2, 2013 at 8:31 am

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

October 2, 2013 at 9:53 am

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

October 2, 2013 at 10:30 am

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.