1

I'm trying to mirror a few folders for a simple backup system.

Let's assume I have the following file structure:

c:\temp\a.txt
c:\temp\b.txt
c:\temp\sub\a.txt
c:\temp\sub\112233.txt
c:\temp\sub2\pictureofaduck.jpg

My objective is to copy the whole content of c:\temp\ to a new destination (D:\mybackup\) like this:

d:\mybackup\a.txt
d:\mybackup\b.txt
d:\mybackup\sub\a.txt
d:\mybackup\sub\112233.txt
d:\mybackup\sub2\pictureofaduck.jpg

I wrongly assumed that this should be an easy task for Copy-Item using this line:

Copy-Item 'C:\temp\' -Destination 'D:\mybackup\' -Recurse

Contrary to my expectation, Copy-Item is really eager to keep that "temp" folder in the game. Because what whatever wildcard and -at the end combinations I try, I either get the following result or only the two files a.txt & b.txt copied.

d:\mybackup\temp\a.txt
d:\mybackup\temp\b.txt
d:\mybackup\temp\sub\123.txt
d:\mybackup\temp\sub\112233.txt
d:\mybackup\temp\sub2\pictureofaduck.jpg

Please help me, this is ridiculous.

PS: the solution to this question here doesn't work - been there. I get only the root files:

Copy entire folder structure in Powershell without re-creating root folder

marc_s
  • 732,580
  • 175
  • 1,330
  • 1,459
Stefan Lippeck
  • 381
  • 2
  • 17

3 Answers3

3

I'm really prefer Xcopy or RoboCopy for that jobs, but if you really want to use Copy-Item:

Get-ChildItem C:\temp -Recurse | % {Copy-Item $_.FullName D:\mybackup}

using Xcopy:

xcopy C:\temp D:\mybackup /e

using RoboCopy:

robocopy C:\temp D:\mybackup /e
Avshalom
  • 8,657
  • 1
  • 25
  • 43
  • this brings me already a little closer, but in this case, all the files end up in D:\backup\ (and if there are files with the same name, they overwrite each other) - But you put me in the right direction. I'll put up my solution soon – Stefan Lippeck Jun 13 '18 at 14:19
1

I found the answer thanks to @Avshalom 's input. I wrote myself a litte function for future usage:

function myCopyFolder([string] $sourceFolder, [string] $destFolder) {
    $i = 0
    Get-ChildItem $sourceFolder -Recurse | % {
        $destName = $_.FullName
        $destName = $destName.Replace($sourceFolder, '')
        Write-Host $_.FullName -Destination (Join-Path $destFolder $destName)
        $i = $i + 1
    }
    write-host $i 'files' copied
}

now i get a complete copy like xcopy would do it. I also tried implementing filters but with them i'd have to find a way to copy the folders separately if needed. - It does what i was looking for.

i added filtering by file type: (empty folders wont be copied with filter)

function myCopyFolder([string] $sourceFolder, [string] $destFolder, [string] $filter) {
    $i = 0
    Get-ChildItem $sourceFolder -Recurse -Filter $filter | % {
        $destName = $_.FullName
        $destName = $destName.Replace($sourceFolder, '')
        $subFolder = $destName.Replace($_.Name, '').Replace('\','')
        if ($subFolder -ne '') {
            if (-not (Test-Path (Join-Path $destFolder $subFolder))) {
                mkdir (Join-Path $destFolder $subFolder)
            }
        }
        Copy-Item $_.FullName -Destination (Join-Path $destFolder $destName)
        $i = $i + 1
    }
    write-host $i 'files' copied
}
Stefan Lippeck
  • 381
  • 2
  • 17
  • As an aside, the `[string]` type modifiers in the function definition may not be doing what you expect - they do not imply that you can only pass in strings, but instead mean "I'll accept anything that is a string or can be converted to one". Since every object in .NET has a `ToString()` method anything (`Int`, `DateTime`, `WebClient`, `Guid`, etc) you pass will be accepted (i.e. converted to a string) and the resulting behaviour might be unexpected, even disastrous. – boxdog Jun 13 '18 at 15:05
1

Another workaround might be to use Copy-Item followed byMove-Item

Copy-Item 'C:\temp\' -Destination 'D:\' -Recurse
Move-Item 'D:\temp\' -Destination 'D:\mybackup'

This does have the caveats that

  • D:\temp doesn't already exists. If it does, you'll end up overwriting/moving other files
  • D:\mybackup doesn't already exists
Lieven Keersmaekers
  • 57,207
  • 13
  • 112
  • 146