Как использовать PowerShell copy-item и сохранить структуру - PullRequest
36 голосов
/ 25 марта 2011

У меня есть структура каталогов, которая выглядит следующим образом:

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

Я хочу скопировать содержимое папок f1 в C: \ tmp \, чтобы получить

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

Я пробовал это:

Copy-Item -recur -path: "*/f1/" -destination: C:\tmp\

Но он копирует содержимое без правильного копирования структуры.

Ответы [ 9 ]

44 голосов
/ 11 сентября 2014

В PowerShell версии 3.0 и новее это просто делается следующим образом:

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

Ссылка: Get-ChildItem

13 голосов
/ 25 марта 2011

Используйте xcopy или robocopy, оба из которых были разработаны именно для этой цели. Предполагая, что ваши пути - это только пути файловой системы, конечно.

11 голосов
/ 06 марта 2012

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
    }

Примечание:

  • -фильтр "*" ничего не делает.Это просто для иллюстрации, если вы хотите скопировать некоторые конкретные файлы.Например, все * .config файлы.
  • Еще нужно вызвать New-Item с -Force, чтобы фактически создать структуру папок.
8 голосов
/ 20 августа 2014

Я копался и нашел множество решений этой проблемы, причем все они были неким простым изменением, а не просто командой copy-item.Конечно, некоторые из этих вопросов предшествуют PowerShell 3.0, поэтому ответы не являются неправильными, но с помощью PowerShell 3.0 я наконец смог добиться этого, используя переключатель -Container для Copy-Item:

Copy-Item $from $to -Recurse -Container

я выполнил тест, ошибок нет, и папка назначения представляла ту же структуру папок:

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, and
#       it does not create the folder1 container
#Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2 -Recurse -Container

# If the destination does not exist, this created the
# matching folder structure and file with no errors
Copy-Item D:\tmp\test_copy\* D:\tmp\test_copy2\ -Recurse -Container
4 голосов
/ 15 марта 2014

Если вы хотите правильно копировать структуру папок с помощью PowerShell, сделайте это следующим образом:

$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
}

Это позволяет создавать каталоги и просто копировать файлы.Конечно, вам нужно изменить приведенный выше вызов Contains (), если ваши папки содержат точки, или добавить фильтр, если вы хотите найти «f1», как вы упомянули.

3 голосов
/ 25 марта 2011

Переключатель Container (для Copy-Item) поддерживает структуру папок. Наслаждайтесь.

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 -force}}

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>>
2 голосов
/ 02 марта 2012

Мне нужно было сделать то же самое, поэтому я нашел эту команду:

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

А в вашем случае:

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

И если вам нужно исключить некоторые элементы, создайтетекстовый файл со списком исключений.Например:

Создайте текстовый файл 'exclude.txt' на диске C: \ и добавьте в него следующее:

.svn
.git

И ваша команда копирования теперь будет выглядеть так:

XCopy c:\folderA\folderB\folderC c:\tmp /EXCLUDE:c:\exclude.txt /E /C /I /F /R /Y
1 голос
/ 14 ноября 2016

У меня сработало следующее

@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"
    )

Для каждой строки (файла) в списке, создайте в целевой папке один и тот же путь, указанный в строке чтения (%% ~ pa - это путьэлемента, на который ссылается %% a).Затем скопируйте прочитанный файл в целевую папку.

0 голосов
/ 08 марта 2019
$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
}

Этот код работает, особенно если вы используете Get-ChildItem в связи с методом filter / where-object.

Однако в этом коде есть одна незначительная ошибка: «IF»оператор и следующий код «mkdir», папка в $ targetDir будет создана ... после этого команда «copy-item» создаст ту же папку в папке, только что созданной командой «mkdir».1006 * Вот пример того, как это работает для меня с функцией «Где-Объект».Вы можете просто опустить оператор IF.

$Sourcefolder= "C:\temp1"
$Targetfolder= "C:\temp2"


$query = Get-ChildItem $Sourcefolder -Recurse | Where-Object {$_.LastWriteTime -gt [datetime]::Now.AddDays(-1)}
$query | % {
    $dest = $Targetfolder + $_.FullName.SubString($Sourcefolder.Length)
    Copy-Item $_.FullName -Destination $dest -Force
}

Убедитесь, что пути не обозначены символом "\" в конце.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...