Search
Write a publication
Pull to refresh

Копирование структуры папок без содержимого с помощью PowerShell

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

Постоянно работая с Powershell, я решил, что с его помощью легко смогу решить данную задачу. Первое что мне пришло в голову это вот такой код:

Copy-Item $source -Destination $destination -Recurse -Exclude *.*

но увы, как я выяснил, оказалось что при использовании параметра -Recurse, параметр -Exclude *.* не работает, он работает только без него.
И при выполнении данного кода копировалось все, включая содержимое всех папок. Я перепробовал еще несколько вариантов, но по прежнему желаемого результат не удалось добиться. Я начал искать решение в интернете, но ничего не нашел, были лишь альтернативные варианты решения при помощи сторонних утилит. Мне стало принципиально интересно решить данную задачу с помощью PowerShell.
Сначала я получал все папки, которые мне нужно было перенести на новое хранилище вот такой строкой:

$folders = Get-ChildItem $path -Recurse | ?{$_.PsIsContainer -eq $true}

переменная $folders содержит все мне необходимые папки, но она не содержит их структуры и при выполнение например такого кода:

$folders | Copy-Item $source -Destination $destination -Recurse

копируется опять же все содержимое вместе с файлами. А если делать так:

New-Item -ItemType directory $folders

то он создаст все папки в одной директории без сохранения структуры.
Я решил просмотреть свойства объектов моего массива $folders и нашел параметр FullName который содержал полный путь до папки, включая ее саму. Это не совсем то что нужно, так мне не нужно было копировать всю структуру с корня диска, а нужна была лишь ее часть. Например, FullName = 'C:\dir1\dir2\dir3\dir4\.....\dirN' и мне нужна структура начиная скажем с папки 4 и все что лежит далее в ней, в этом случае FullName мне не подходит. Однако ничего не мешает нам выбрать из этого пути того что нам нужно путем разбора строки.
В результате у меня получился простенький скрипт:

$path = Get-ChildItem Z:\Backup\Dir1 -Recurse | ?{$_.PsIsContainer -eq $true}
$dest = «C:\test\»
$parent = $path[0].Parent.Name
$path | foreach {

$_.FullName -match "$parent.+"
New-Item -ItemType directory ($dest + $Matches[0])

}

Сначала он забирает все папки в переменную $path.
Переменная $dest содержит путь, куда мы хотим скопировать структуры.
Затем в переменную $parent я помещаю «родителя» моей структуры, в данном случае это папка Dir1.
Далее перебирая все элементы я выполняю разбор строки параметра FullName(его результат выглядит так: Dir1\...\....\...\… а далее вся структура папок).
И затем просто создаю заново эту структуру в нужном мне месте.

Как оказалось все просто.

P.S. Есть небольшие нюансы при разборе строки параметра FullName, например если имя нашего $parent дублируется где внутри пути, а именно если наша родительская папка вложена в какую-нибудь папку с аналогичным ей именем, то результат разбора строки может быть иным нежели мы ожидаем. Впрочем там просто нужно немного поработать с регулярными выражениями и получить нужный результат.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.