Копирование файлов из нескольких (указанных) путей к папкам в другой каталог при сохранении файловой структуры

Я пытаюсь скопировать несколько файлов из одного каталога в другой с помощью PowerShell. Я бы хотел:

  • Поддерживать структуру папок / файлов.
  • Скопируйте все файлы в определенных папках.

Гипотетическая структура:

Исходная папка \ Пользователь 1
        \ Папка 1
        \ Файлы \ Папка 2
            \ Файлы \ Папка 3
            \ Файлы \ Пользователь 2
            \ Папка 3
            \ Файлы \ Пользователь 3
            \ Папка 2
            \ Файлы \ Пользователь 4
        \ Папка 3
            \ Файлы \ Папка 4
        \ Файлы

Возможный сценарий:

  • Я хочу скопировать файлы, где у пользователей есть папка 1 и папка 2.

Ожидаемый результат:

Папка назначения
    \ Пользователь 1
        \ Папка 1
            \Files
        \ Папка 2
            \Files
        \ Пользователь 3
        \ Папка 2
            \ Files

Это код, который я до сих пор:

$FolderName = '\\Folder 1\\'
$source = 'C:\CDPTest\Live'
$target = 'C:\CDPTest\DevTest'
$source_regex = [regex]::Escape($source)

(gci $source -Recurse | where {-not ($_.PSIsContainer)} | select -Expand FullName) -match $FolderName |
    foreach {
        $file_dest = ($_ | Split-Path -Parent) -replace $source_regex, $target
        if (-not (Test-Path $file_dest)) {mkdir $file_dest}
    }

Как вы можете видеть, совпадение вернет только один путь к файлу на основе текущего кода, и я пытаюсь расширить его, чтобы он соответствовал нескольким именам папок.

Что я пробовал:

  • Запуск этого кода с другим именем папки в отдельном файле PowerShell безуспешно.
  • Использование массива имен папок для сопоставления.
  • С использованием -and/-or операторы для расширения функции соответствия.

2 ответа

Решение

Благодаря всем ответам на этот вопрос, вы все помогли указать мне правильное направление. Это решение, которое я выбрал:

#Used for time-stamped logs (requires C:\Root\RobocopyLogs\ to exist)
#$log can be added after '$dest$'
#$dateTime = Get-Date -Format g
#$currentDateTime = get-date -format "MM.dd.yyyy-HH.mm.ss.fff"
#$log = "/log:C:\Root\RobocopyLogs\$currentDateTime.txt"

# Set up variables
$sourceRootDirectory = "C:\Root\Source"
$userDirectories = $sourceRootDirectory+"\*\"
$dest = "C:\Root\Destination"
$excludeExceptions = @("Folder 1",
"Folder 2",
"Folder 3",
"Folder 4",
"Folder 5")

# Get the exclusion list from the source
$excludedFolderArray = (gci $userDirectories -Exclude $excludeExceptions)
$excludedFileArray = $excludedFolderArray |
    Where-Object {$_.PSIsContainer -eq $False}

Robocopy $sourceRootDirectory $dest /FFT /MIR /XA:H /R:1 /W:5 /XD $excludedFolderArray /XF $excludedFileArray

У меня возникла проблема при синхронизации с robocopy, где, если файл был помещен в корневую папку, он был бы скопирован. Пришлось создать отдельный список файлов, которые нужно исключить из корня.

Хотя Robocopy все еще может быть лучшим подходом,
этот сценарий определяет папки для копирования в первую очередь (с помощью или | RegEx), а затем создает папку назначения и создает ее при необходимости. (Непроверенные)

$FolderName = [regex]('\\Folder 1$|\\Folder 2$')
$source = 'C:\CDPTest\Live'
$target = 'C:\CDPTest\DevTest'
Get-ChildItem $source -Recurse | 
  Where-Object {$_.PSIsContainer -and $_.FullName -match $FolderName} |
    Foreach-Object {
      $targetFolder = Join-Path $target ($_.FullName -replace [RegEx]::escape($source),'')
      if (!(Test-Path $targetFolder)) {mkdir $targetFolder|Out-Null}
      Copy-Item -Path $_ -Filter * -Destination $targetFolder
    }
Другие вопросы по тегам