Public/File/Split-DirectoryContentsToSubfolders.ps1
<#
.SYNOPSIS Splits the contents of directories into subfolders. .DESCRIPTION The Split-DirectoryContentsToSubfolders function splits the contents of the specified directories into subfolders. The number of entries per subfolder can be specified. The function can process either files or folders. .PARAMETER Directories Specifies the directories to process. This parameter accepts pipeline input and can be a string, or an object with a Path, FullName, or PSPath property. .PARAMETER ProcessFolders If this switch is present, the function will process folders instead of files. .PARAMETER NumEntriesPerFolder Specifies the number of entries per subfolder. The default is 1000. .PARAMETER FolderNumberPadding Specifies the number of digits to use for the folder number. The default is 2. .PARAMETER PathPrefix Specifies the prefix to use for the path. The default is 'None'. This parameter can be 'None' or 'FolderName'. If 'None' is passed, the folders do not get a prefix. If 'FolderName' is passed, the folders get a prefix consisting of their parent folder. .EXAMPLE Split-DirectoryContentsToSubfolders -Directories "C:\Temp" -NumEntriesPerFolder 500 This example splits the contents of the "C:\Temp" directory into subfolders, with 500 entries per subfolder. .EXAMPLE Get-ChildItem -Path "C:\Temp" | Split-DirectoryContentsToSubfolders -NumEntriesPerFolder 200 -FolderNumberPadding 3 This example gets the child items of the "C:\Temp" directory and passes them to the Split-DirectoryContentsToSubfolders function, which splits them into subfolders with 200 entries per subfolder and 3-digit folder numbers. .EXAMPLE Split-DirectoryContentsToSubfolders -Directories "C:\Temp" -ProcessFolders -PathPrefix "FolderName" This example processes the folders in the "C:\Temp" directory and splits them into subfolders. The subfolders are named with the prefix of their parent folder. .EXAMPLE Split-DirectoryContentsToSubfolders -Directories "C:\Temp" -PathPrefix "None" This example splits the contents of the "C:\Temp" directory into subfolders, with no prefix for the subfolders. .AUTHOR Futuremotion https://www.github.com/fmotion1 #> function Split-DirectoryContentsToSubfolders { [CmdletBinding(DefaultParameterSetName="Prefix")] param ( [parameter( Mandatory, Position = 0, ValueFromPipeline, ValueFromPipelineByPropertyName )] [ValidateNotNullOrEmpty()] [Object[]] $Directories, [Switch] $ProcessFolders, [Int32] $NumEntriesPerFolder = 1000, [Int32] $FolderNumberPadding = 2, [parameter( ValueFromPipelineByPropertyName, ParameterSetName='Prefix' )] [ValidateSet('None','FolderName', IgnoreCase = $true)] [String] $PathPrefix = 'None' ) begin { $List = [System.Collections.Generic.List[String]]@() } process { foreach ($P in $Directories) { $Path = if ($P -is [String]) { $P } elseif ($P.Path) { $P.Path } elseif ($P.FullName) { $P.FullName } elseif ($P.PSPath) { $P.PSPath } else { Write-Error "$P is an unsupported type."; throw } # Resolve paths $ResolvedPaths = Resolve-Path -Path $Path foreach ($ResolvedPath in $ResolvedPaths) { if (Test-Path -Path $ResolvedPath.Path -PathType Container) { $List.Add($ResolvedPath.Path) } else { Write-Warning "$ResolvedPath does not exist on disk." } } } } end { foreach ($Dir in $List) { Set-Location -LiteralPath $Dir $DirObject = Get-Item -LiteralPath $Dir $CreateNewFolder = { $Prefix = if($PathPrefix -eq 'none') { '' } else { $DirObject.BaseName } $NewChunk = $Index + 1 $IndexFormatted = $NewChunk.ToString().PadLeft($FolderNumberPadding, '0') $FormatDirName = if(-not($ProcessFolders)) { "$Prefix $IndexFormatted".Trim() } else { (Get-RandomAlphanumericString -Length 10) + "-$Prefix $IndexFormatted".Trim() } $OutputDirectory = [IO.Path]::Combine($DirObject.FullName, "$FormatDirName") [IO.Directory]::CreateDirectory($OutputDirectory).FullName } $Enumeration = if($ProcessFolders) { $DirObject.EnumerateDirectories() } else { $DirObject.EnumerateFiles() } foreach ($Object in $Enumeration) { if($i++ % $NumEntriesPerFolder -eq 0) { $NewFolder = (& $CreateNewFolder) $Index++ } $Dest = "$NewFolder\$($Object.Name)" [System.IO.Directory]::Move($Object.FullName, $Dest) | Out-Null } if($ProcessFolders) { Get-ChildItem -LiteralPath $DirObject -Directory | % { $folderName = Split-Path -Path $_ -Leaf $newFolderName = ($folderName -replace '^[^-]*-', '').TrimStart() $parentPath = Split-Path -Path $_ -Parent $newFolderPath = Join-Path -Path $parentPath -ChildPath $newFolderName Rename-Item -Path $_ -NewName $newFolderPath -Force | Out-Null } } } } } |