Вопрос или проблема
У меня есть большая папка с множеством подкаталогов и файлов. Мне интересно скопировать только определенные файлы из этой большой папки в новую папку вместе со структурой папок. Я использую 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 “из коробки”, и все, что вам нужно, есть в файлах помощи:
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 инициативам!