steve_o
steve_o

Reputation: 1243

Copy folders without files, files without folders, or everything using PowerShell

I would like to be able to write a PowerShell script that would take a folder (or set of folders) and to duplicate them in which the folder structure (without the files) could be created, where the file structure (without the folders) could be created, or in which both the files (all or selected ones) AND folders could be created.

    Example:

    C:\ProdData has 3 subfolders in it
    C:\ProdData\Fld1
    C:\ProdData\Fld2
    C:\ProdData\Fld3 - has 2 subfolders under it
    C:\ProdData\Fld3\MyFolder1
    C:\ProdData\Fld3\MyFolder2

Each folder above has a various number of files of various sizes in it, of various file extensions.

I would like to have a PowerShell script that would duplicate that folder structure elsewhere, giving me a choice of Folder Structure Only, Files Only, or Files AND Folders to be copied.

In the above, I'd like to be able to copy C:\ProdData to another folder, essentially renaming ProdData to TestData (that is, C:\ProdData copied to C:\TestData), or to copy the entire folder structure.

C:\ProdData into another folder that is a subfolder of something else: C:\TestArea\TestFolders\2012-04-01\TestData\ProdData\Fld1, etc...

And selectively choose to include folders, files or both.

The ideal solution would be to (for folders only) take the folder structure, export/save it, read it in, and create that same structure elsewhere. Some solutions I've found said they copied the folder structure only, but if data exists, that gets copied also and you can't exclude one or the other. I have a partial solution to the files-only requirement that semi-preserves the path, but it would take a file:

c:\ProdData\Fld1\MyFile.dat

and copy it to:

c:\TestData\yyyyMMdd_hhmmss_ProdData_Fld1_MyFile.dat

But that's not something that could easily be decoded and would be impossible to re-integrate the source structure. I'd appreciate any thoughts about how to accomplish this without re-inventing the wheel.

Upvotes: 31

Views: 64283

Answers (4)

Esperento57
Esperento57

Reputation: 17472

I propose my solution :

$source = "C:\temp\"
$dest = "C:\TestData\"

#create destination directory if dont exist
New-Item -ItemType Directory $dest -Force


#To copy everything in a folder hierarchie
Get-ChildItem $source -Recurse | Copy-Item -Destination {$_.FullName.Replace($source, $dest)}  -Force

#To copy only directory hierarchie:
Get-ChildItem $source -Recurse -directory | Copy-Item -Destination {$_.FullName.Replace($source, $dest)}  -Force

#To copy only file (remove doublon be carefull):
Get-ChildItem $source -Recurse -file | Copy-Item -Destination $dest -Force

Upvotes: 7

Fred B
Fred B

Reputation: 193

The following copies just the folder structure form ProdData to TestData without any files

$from = "C:\ProdData"
$to = "C:\TestData"

Get-ChildItem -Path $from -Recurse | 
?{ $_.PSIsContainer } | 
Copy-Item -Destination {Join-Path $to $_.Parent.FullName.Substring($from.length)} -Force 

Upvotes: 1

Reinout
Reinout

Reputation: 485

To copy everything in a folder hierarchie

Copy-Item $source $dest -Recurse -Force

To copy the hierarchie you can try:

$source = "C:\ProdData"
$dest = "C:\TestData"
Copy-Item $source $dest -Filter {PSIsContainer} -Recurse -Force

To flatten a file structure you can try:

$source = "C:\ProdData"
$dest = "C:\TestData"
New-Item $dest -type directory
Get-ChildItem $source -Recurse | `
    Where-Object { $_.PSIsContainer -eq $False } | `
    ForEach-Object {Copy-Item -Path $_.Fullname -Destination $dest -Force} 

Good luck!

Upvotes: 37

ajk
ajk

Reputation: 4603

Here are some ideas for handling each situation you describe.

Folder Structure Only

This will copy the source to a destination, recursing subdirectories but excluding all files.

robocopy $source $dest /e /xf *.*

Files Only (Flatten Structure)

There are a few ways to handle this, but I don't know of an especially good or elegant way. Here's an awkward but effective approach - for each subdirectory, it runs a non-recursive copy to a root destination folder. Criticism or nicer alternatives would be most welcome.

Get-ChildItem $source -Recurse |
  Where-Object { $_.PSIsContainer -eq $true } |
  Foreach-Object { robocopy $_.FullName $dest }

Everything

This scenario is the most straightforward of the bunch.

robocopy $source $dest /e

You can experiment with the switches yourself (referencing robocopy /? along the way) to fine tune the process. The trickiest scenario in my opinion is the one that flattens the directory structure. You'll have some decisions to make, like how you want to handle the same file name appearing in multiple directories.

As for how to accept options from the command line, I'd suggest putting together Powershell parameter sets for your three situations. There are a number of blog posts around that discuss the concept, but you can also see TechNet or run help about_Functions_Advanced_Parameters inside Powershell.

Upvotes: 35

Related Questions