Раскладываем файлы по папкам (PoSh) (готовим структуру электронного архива)
По долгу службы работаю также с подрядчиками нашего производства. Естественно, передавать им изменения в документации бумагами накладно, а в некоторых случаях – недопустимо (подрядчики есть и за 200, и за 800 км). Поэтому озаботился вопросом создания некоего централизованного хранилища чертежей (уже в общеупотребимом виде (.tif, .xps)) и прочих технических документов и для себя, и для подрядчиков. Для этих целей выбрал Subversion + TortoiseSVN + PowerShell.
О TortoiseSVN и о создании репозитория уже писал, повторяться не буду. Задача для данной статьи крайне простая:
- Имею папку, в которой уже лежат файлы следующего вида:
XXXX.XX.XX.XXX.tif (.mdi)
, где X – децимальный номер документа в соответствии с ЕСКД. Сам файл, как уже понятно, содержит “картинку” чертежа или другого документа, определяющего требования к детали / узлу. - Учитывая тот факт, что в некоторых случаях требования могут определяться не одним документом, а несколькими, решил всё-таки разложить указанные файлы по подпапками вида. Например, для файла
К309.01.02.009.tif
создаём иерархию папокК309\01\02\009\_self
, куда уже и выкладываем все файлы для указанной детали.
Выполним эту простейшую задачу средствами powershell. Взаимодействие сценария с subversion на этом этапе не требуется, просто подготовим структура для импорта в репозиторий subversion.
<# .Synopsis Раскладываем файлы по подпапкам. .Description Получает на вход либо объект, либо путь к папке, содержащей файлы. Создаёт подпапки в папке (второй аргумент, если не указан, то подпапки создаются в исходной папке) с именами, совпадающими с именами файлов (без учёта расширения). Файлы переносит в созданные подпапки. .Parameter sourceFolder Каталог, файлы которого будут обработаны .Parameter destFolder Каталог, в котором будет создана требуемая структура .Parameter searchPattern Маска для поиска файлов. .Parameter splitter Символы - разделители в имени файла для выделения дочерних папок. .Example Раскладываем файлы по папкам "на месте", в исходной папке. .\FilesToFolder.ps1 "X:\Порталы\Аутсорсинг\Процессы\Гальванические покрытия\Чертежи" #> param ( [Parameter( Mandatory=$true, Position=0, ValueFromPipeline=$true, HelpMessage="Source folder." )] [System.IO.DirectoryInfo] $sourceFolder, [Parameter( Mandatory=$false, Position=1, ValueFromPipeline=$false, HelpMessage="Destination folder." )] [System.IO.DirectoryInfo] $destFolder = "c:\temp\test22", [Parameter( Mandatory=$false, Position=2, ValueFromPipeline=$false, HelpMessage="File mask." )] [string] $searchPattern = '*.*', [Parameter( Mandatory=$false, Position=3, ValueFromPipeline=$false, HelpMessage="File name splitter." )] [string] $splitter = '\.|-' ) $files = @(get-childItem ` -path $sourceFolder ` -filter $searchPattern ` ); $files | % ` -begin { [int]$fileIndex = 0; write-progress ` -id 1 ` -activity 'Переносим файлы в древовидную структуру папок' ` -status 'Приступаем...' } ` -process { copy-item ` -path ($_.FullName) ` -destination ( ` new-item ` -path ( (([System.IO.Path]::GetFileNameWithoutExtension($_.Name)) -split $splitter) ` | % ` -begin { [string]$newSubFolder = $destFolder; } ` -process { $newSubFolder = join-path -path $newSubFolder -childPath $_; } ` -end { $newSubFolder } ) ` -type directory ` -force ) $fileIndex++; write-progress ` -id 1 ` -activity 'Переносим файлы в древовидную структуру папок' ` -status 'Переносим файлы' ` -currentOperation "$($_.Name) ($($fileIndex) из $($files.count))" ` -percentcomplete ($fileIndex/$files.count*100) } ` -end { write-progress ` -id 1 ` -activity 'Переносим файлы в древовидную структуру папок' ` -status 'Завершили...' ` -completed }
Как видно, мы прицепили к сценарию и прогресс-бар (советую).
В результате выполнения сценария получаем иерархическую систему папок со скопированными в неё исходными файлами (на рисунке слева).
P.S. Совершенно справедливо можно подметить, довольно громоздкую конструкцию можно было бы заменить банальной заменой .
в имени файла на \
одним оператором. Но я сознательно нарисовал код с использованием join-path
с тем, чтобы кросс-платформенным, и не зависел от провайдера (теоретически, этот сценарий будет прекрасно работать не только для файловой системы).
P.P.S. Также должен обратить внимание на тот факт, что отображённый на картинке результат не совсем соответствует результату работы выше приведённого сценария. Сценарию был задан параметр –splitter '(Э)|(СТС)|(СТМ)|(СТН)|(ЛТК)|(КАД)|(Л)|(ШМГ)|(К)|(А)|(?:[\.|-])'
(так как в моём случае не все элементы группировки файлов явным образом выделены разделителями в имени файла). Подробнее подобное применение оператора –split
рассматриваю в отдельной статье.
RSS комментарии
Обратная ссылка