PowerShell – Копирование файла в другую папку с сохранением структуры папок

Вопрос или проблема

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

Я могу сделать это с помощью кодирования на Python или Java, но мне нужно запустить это на удаленном сервере, где у меня есть доступ только к Powershell. У меня нет большого опыта работы с Powershell.

Я попробовал поискать документацию и в интернете и нашел следующие две команды:

1) Copy-Item -Path LargeFolder\folder1\sub-folder1\file1.txt -Destination NewFolder\ -Recurse
2) Get-ChildItem -Path LargeFolder\folder1\sub-folder1\file1.txt | Copy-Item -Destination NewFolder\ -Recurse -Container

Обе команды копируют только file1.txt в NewFolder без структуры папок.

Вывод обеих команд:

NewFolder
 |- file1.txt

Ожидаемый вывод:

NewFolder
  |-folder1
    |-sub-folder1
      |-file1.txt

//или даже это, я не возражаю против лишней корневой папки
NewFolder
  |-LargeFolder
    |-folder1
      |-sub-folder1
        |-file1.txt

Я немного запутался. Как мне также сохранить структуру папок?

Вам нужно создать структуру подпапок перед тем, как скопировать файл:

$Destination = 'NewFolder'
$FileToCopy = 'LargeFolder\folder1\sub-folder1\file1.txt'

Get-Item $fileToCopy | Copy-Item -Destination {
    $DestPath = Join-Path $Destination (( $_.DirectoryName -Split 'LargeFolder' )[-1] )
    If ( ! ( Test-Path )) { mkdir $DestPath | out-null }
    $DestPath
}

Вы можете сделать это с помощью Robocopy (с участием PowerShell или без него) или Copy-Item “из коробки”, и все, что вам нужно, есть в файлах помощи:

‘PowerShell using robocopy’

Youtube – ‘PowerShell copy-item’

Robocopy /?
-------------------------------------------------------------------------------
   ROBOCOPY     ::     Надежное копирование файлов для Windows                              
-------------------------------------------------------------------------------

  Начато : Среда, 26 августа, 2020 08:40:06
              Использование  :: ROBOCOPY источник назначение [файл [файл]...] [опции]

             источник  :: Исходный каталог (диск:\путь или \\сервер\общий ресурс\путь).
        назначение :: Каталог назначения (диск:\путь или \\сервер\общий ресурс\путь).
               файл :: Файлы для копирования (имена/шаблоны: по умолчанию "*.*").

::
:: Опции копирования :
::
                 /S :: копировать подкаталоги, но не пустые.
                 /E :: копировать подкаталоги, включая пустые.
             /LEV:n :: копировать только верхние n уровней дерева исходного каталога.

                 /Z :: копировать файлы в режиме перезапуска.
                 /B :: копировать файлы в режиме резервного копирования.
                /ZB :: использовать режим перезапуска; если доступ запрещен, использовать режим резервного копирования.
                 /J :: копировать, используя неблокированную В/О (рекомендуется для больших файлов).
            /EFSRAW :: копировать все зашифрованные файлы в режиме EFS RAW.

  /COPY:copyflag[s] :: что копировать для файлов (по умолчанию /COPY:DAT).
                       (copyflags : D=Данные, A=Атрибуты, T=Временные метки, X=Пропустить альтернативные потоки данных).
                       (S=Безопасность=NTFS ACL, O=Информация о владельце, U=Информация для аудита).

               /SEC :: копировать файлы с безопасностью (эквивалентно /COPY:DATS).
           /COPYALL :: копировать всю информацию о файле (эквивалентно /COPY:DATSOU).
            /NOCOPY :: не копировать никакую информацию о файле (полезно с /PURGE).
            /SECFIX :: исправить безопасность файла для всех файлов, даже пропущенных.
            /TIMFIX :: исправить время файла для всех файлов, даже пропущенных.

             /PURGE :: удалить файлы/каталоги назначения, которых больше нет в источнике.
               /MIR :: отражать дерево каталогов (эквивалентно /E плюс /PURGE).
 ...

Youtube ‘PowerShell copy-item’

# Получить детали для модуля, командлета или функции
(Get-Command -Name Copy-Item).Parameters
(Get-Command -Name Copy-Item).Parameters.Keys
# Результаты
<#
Path
LiteralPath
Destination
Container
Force
Filter
Include
Exclude
Recurse
PassThru
Credential
Verbose
Debug
ErrorAction
WarningAction
InformationAction
ErrorVariable
WarningVariable
InformationVariable
OutVariable
OutBuffer
PipelineVariable
WhatIf
Confirm
UseTransaction
FromSession
ToSession
#>
Get-help -Name Copy-Item -Examples
# Результаты
<#
Copy-Item "C:\Wabash\Logfiles\mar1604.log.txt" -Destination "C:\Presentation"
Copy-Item "C:\Logfiles" -Destination "C:\Drawings" -Recurse
Copy-Item C:\Logfiles -Destination C:\Drawings\Logs -Recurse
Copy-Item "\\Server01\Share\Get-Widget.ps1" -Destination "\\Server12\ScriptArchive\Get-Widget.ps1.txt"
$Session = New-PSSession -ComputerName "Server01" -Credential "Contoso\PattiFul"
 Copy-Item "D:\Folder001\test.log" -Destination "C:\Folder001_Copy\" -ToSession $Session
$Session = New-PSSession -ComputerName "Server02" -Credential "Contoso\PattiFul"
 Copy-Item "D:\Folder002\" -Destination "C:\Folder002_Copy\" -ToSession $Session
$Session = New-PSSession -ComputerName "Server04" -Credential "Contoso\PattiFul"
 Copy-Item "D:\Folder003\" -Destination "C:\Folder003_Copy\" -ToSession $Session -Recurse
$Session = New-PSSession -ComputerName "Server04" -Credential "Contoso\PattiFul"
 Copy-Item "D:\Folder004\scriptingexample.ps1" -Destination "C:\Folder004_Copy\scriptingexample_copy.ps1" -ToSession $Session
$Session = New-PSSession -ComputerName "Server01" -Credential "Contoso\PattiFul"
 Copy-Item "C:\MyRemoteData\test.log" -Destination "D:\MyLocalData\" -FromSession $Session
$Session = New-PSSession -ComputerName "Server01" -Credential "Contoso\PattiFul"
 Copy-Item "C:\MyRemoteData\scripts" -Destination "D:\MyLocalData\" -FromSession $Session
$Session = New-PSSession -ComputerName "Server01" -Credential "Contoso\PattiFul"
 Copy-Item "C:\MyRemoteData\scripts" -Destination "D:\MyLocalData\scripts" -FromSession $Session
#>
Get-help -Name Copy-Item -Full
Get-help -Name Copy-Item -Online

Вы можете сделать это так:

$inFilename = "folder1\sub-folder1\file1.txt"
New-Item -Path (Split-Path "NewFolder\$inFilename" -Parent) -ItemType Directory -Force; # Создать подструктуру папок
    Copy-Item -Path $inFilename -Destination "NewFolder\$inFilename" # Скопировать файл

Вы можете использовать это в цикле для нескольких имен файлов, включая пути, если необходимо

Ответ или решение

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

Теоретическая основа

В Windows для решения подобных задач имеется утилита Robocopy, которая при правильной настройке позволяет сохранять структуру каталогов при копировании файлов. Однако, если ваша задача – использовать исключительно PowerShell, вы можете вручную обеспечить создание структуры каталогов перед фактическим копированием файлов. Основной подход заключается в разбиении полного пути файла и рекурсивном создании необходимых директорий в новом месте перед фактическим копированием файла.

Пример решения

Рассмотрим рабочий скрипт на PowerShell, который иллюстрирует описанный подход:

# Определение исходного и целевого путей
$SourceFolder = "LargeFolder"
$DestinationFolder = "NewFolder"
$FileToCopy = "folder1\sub-folder1\file1.txt"

# Создание полного пути исходного и целевого файла
$SourcePath = Join-Path -Path $SourceFolder -ChildPath $FileToCopy
$DestinationPath = Join-Path -Path $DestinationFolder -ChildPath $FileToCopy

# Извлечение пути для создания структуры каталогов в целевом месте
$DestinationDirectory = Split-Path -Path $DestinationPath -Parent

# Проверка и создание необходимых директорий
if (-Not (Test-Path -Path $DestinationDirectory)) {
    New-Item -Path $DestinationDirectory -ItemType Directory -Force
}

# Копирование файла с сохранением структуры каталогов
Copy-Item -Path $SourcePath -Destination $DestinationPath

Применение к задаче

Теперь, когда у нас есть рабочий пример, давайте рассмотрим, как вы можете применить это в реальном мире, если у вас есть множество файлов, которые необходимо скопировать, используя цикл:

$SourceFolder = "LargeFolder"
$DestinationFolder = "NewFolder"
$FilesToCopy = @("folder1\sub-folder1\file1.txt", "folder2\sub-folder2\file2.txt", "folder3\file3.txt")

foreach ($FilePath in $FilesToCopy) {
    $SourcePath = Join-Path -Path $SourceFolder -ChildPath $FilePath
    $DestinationPath = Join-Path -Path $DestinationFolder -ChildPath $FilePath
    $DestinationDirectory = Split-Path -Path $DestinationPath -Parent

    if (-Not (Test-Path -Path $DestinationDirectory)) {
        New-Item -Path $DestinationDirectory -ItemType Directory -Force
    }

    Copy-Item -Path $SourcePath -Destination $DestinationPath
}

Этот скрипт позволит вам копировать каждый файл из списка и сохранять его в соответствующей структуре подкаталогов. Теперь вы сможете добавлять дополнительные файлы в массив $FilesToCopy, и они тоже будут корректно скопированы с сохранением структуры.

Зачем выбирать PowerShell

Выбор PowerShell для этой задачи обусловлен его встроенными возможностями взаимодействия с файловой системой Windows, простотой написания и выполнения скриптов, а также возможностью интеграции с другими системными командами и утилитами. Для ситуаций, когда Python или Java недоступны для использования, PowerShell предлагает достаточно мощные средства для решения большинства задач администрирования и управления системами, как в вашем случае с копированием файлов.

Альтернативы и другие советы

Если в будущем вам будет интересен более автоматизированный метод, вы можете рассмотреть использование утилиты Robocopy, с помощью которой можно выполнять более сложные задания копирования с поддержкой дополнительных атрибутов и параметров. Например, для копирования структуры каталогов вы можете использовать следующий синтаксис:

Robocopy "LargeFolder" "NewFolder" folder1\sub-folder1\file1.txt /E

Однако, если доступ к сторонним утилитам ограничен, PowerShell при правильном подходе будет достаточно надежным и мощным инструментом.

Заключение

Решение ваших задач с PowerShell обеспечивает гибкость и точность, необходимые для управления сложными структурами каталогов и файлами. Будьте уверены, что с использованием правильных методик и инструментов каждый шаг выполняется эффективно и результативно. Удачи вам в ваших IT инициативам!

Оцените материал
Добавить комментарий

Капча загружается...