How to use powershell copy-item and keep structure

2019-01-09 02:29发布

问题:

I have a directory structure that looks like this:

c:\folderA\folderB\folderC\client1\f1\files
c:\folderA\folderB\folderC\client1\f2\files
c:\folderA\folderB\folderC\client2\f1\files
c:\folderA\folderB\folderC\client2\f2\files
c:\folderA\folderB\folderC\client3\f1\files
c:\folderA\folderB\folderC\client4\f2\files

I want to copy the content of the f1 folders in c:\tmp\ to get this

c:\tmp\client1\f1\files
c:\tmp\client2\f1\files
c:\tmp\client3\f1\files

I tried this :

copy-item -recur -path: "*/f1/" -destination: c:\tmp\

But it copies the contents without copying the structure correctly.

回答1:

In PowerShell version 3.0 and newer this is simply done this way:

Get-ChildItem -Path $sourceDir | Copy-Item -Destination $targetDir -Recurse -Container

Reference: Get-ChildItem



回答2:

Use xcopy or robocopy, both of which have been designed for exactly that purpose. Assuming your paths are only filesystem paths, of course.



回答3:

Powershell:

$sourceDir = 'c:\folderA\folderB\folderC\client1\f1'
$targetDir = ' c:\tmp\'

Get-ChildItem $sourceDir -filter "*" -recurse | `
    foreach{ 
        $targetFile = $targetDir + $_.FullName.SubString($sourceDir.Length); 
        New-Item -ItemType File -Path $targetFile -Force;  
        Copy-Item $_.FullName -destination $targetFile 
    } 

Note:

  • The -filter "*" does not do anything. It is just here to illustrate if you want to copy some specific files. E.g. all *.config files.
  • Still have to call a New-Item with -Force to actually create the folder structure.


回答4:

there is another answer here with the same solution though it is not very clear so I will throw this in as it took me a while to find this answer.

I have been digging around and found a lot of solutions to this issue, all being some alteration not just a straight copy-item command. Grant it some of these questions predate PS 3.0 so the answers are not wrong but using powershell 3.0 I was finally able to accomplish this using the -Container switch for copy-item.

Copy-Item $from $to -Recurse -Container

this was the test i ran, no errors and destination folder represented the same folder structure.

New-Item -ItemType dir -Name test_copy
New-Item -ItemType dir -Name test_copy\folder1
New-Item -ItemType file -Name test_copy\folder1\test.txt
#NOTE: with no \ at the end of the destination the file is created in the root of the destination, does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container

#if the destination does not exists this created the matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container

hope this helps someone



回答5:

The Container switch mantain the folder structure. Enjoy.

testing>> tree
Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client2
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client3
│   └───f1
│       └───files
└───client4
    └───f2
        └───files
testing>> ls client* | % {$subdir=(join-path $_.fullname f1); $dest=(join-path temp ($_
.name +"\f1"));if(test-path ($subdir)){ copy-item $subdir $dest -recurse -container -fo
rce}}
testing>> tree
Folder PATH listing
Volume serial number is 12D3-1A3F
C:.
├───client1
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client2
│   ├───f1
│   │   └───files
│   └───f2
│       └───files
├───client3
│   └───f1
│       └───files
├───client4
│   └───f2
│       └───files
└───temp
    ├───client1
    │   └───f1
    │       └───files
    ├───client2
    │   └───f1
    │       └───files
    └───client3
        └───f1
            └───files
testing>>


回答6:

If you want to correctly copy a folder structure correctly with PowerShell, do it like so:

$sourceDir = 'C:\source_directory'
$targetDir = 'C:\target_directory'

Get-ChildItem $sourceDir -Recurse | % {
   $dest = $targetDir + $_.FullName.SubString($sourceDir.Length)

   If (!($dest.Contains('.')) -and !(Test-Path $dest))
   {
        mkdir $dest
   }

   Copy-Item $_.FullName -Destination $dest -Force
}

This accounts for creating directories and just copying the files. Of course you'll need to modify the Contains() call above if your folders contain periods or add a filter if you want to search for "f1" as you mentioned.



回答7:

I needed to do the same thing, so I found this command:

XCopy souce_path destination_path /E /C /I /F /R /Y

And in your case:

XCopy c:\folderA\folderB\folderC c:\tmp /E /C /I /F /R /Y

And if you need to exclude some items, create text file with a list of exclusions. E.g.:

Create text file 'exclude.txt' on drive C:\ and add this in it:

.svn
.git

And your copy command will look like this now:

XCopy c:\folderA\folderB\folderC c:\tmp /EXCLUDE:c:\exclude.txt /E /C /I /F /R /Y


回答8:

Below worked for me

@echo off
    setlocal enableextensions disabledelayedexpansion 

    set "target=e:\backup"

    for /f "usebackq delims=" %%a in ("TextFile.txt") do (
        md "%target%%%~pa" 2>nul
        copy /y "%%a" "%target%%%~pa"
    )

For each line (file) inside the list, create, under the target folder, the same path indicated in the readed line (%%~pa is the path of the element referenced by %%a). Then, copy the readed file to the target folder



标签: powershell