[CmdletBinding(SupportsShouldProcess)]
param(
[Parameter(Position = 0)]
[string]$Path,
[Parameter(Position = 1)]
[string[]]$Name,
[ValidateScript({ Test-Path -LiteralPath $_ -PathType Leaf })]
[string]$NameFile,
[switch]$NoBanner
)
if (-not $NoBanner) {
Write-Host ''
Write-Host '==============================' -ForegroundColor Cyan
Write-Host ' Mass Folder Creation' -ForegroundColor Cyan
Write-Host '==============================' -ForegroundColor Cyan
Write-Host ''
}
while ([string]::IsNullOrWhiteSpace($Path)) {
$Path = (Read-Host 'Parent directory (e.g. D:\Projects)').Trim().Trim('"')
}
if ($NameFile) {
$Name = @($Name) + @(
Get-Content -LiteralPath $NameFile |
ForEach-Object { $_.Trim() } |
Where-Object { $_ }
) | Where-Object { $_ }
}
while (-not $Name) {
$answer = Read-Host 'Folder names, separated by commas (e.g. Docs, Scripts, Backups)'
$Name = $answer -split ',' |
ForEach-Object { $_.Trim().Trim('"') } |
Where-Object { $_ }
}
# Reject characters Windows does not allow in folder names
$invalid = [IO.Path]::GetInvalidFileNameChars() | Where-Object { $_ -notin '\', '/' }
$invalidPattern = '[{0}]' -f [regex]::Escape(-join $invalid)
# Make sure the parent exists
if (-not (Test-Path -LiteralPath $Path)) {
if ($PSCmdlet.ShouldProcess($Path, 'Create parent directory')) {
New-Item -ItemType Directory -Path $Path -Force | Out-Null
}
}
$created = 0; $skipped = 0; $failed = 0
foreach ($folder in $Name) {
if ($folder -match $invalidPattern) {
Write-Warning "Skipping '$folder': contains invalid characters."
$failed++
continue
}
$target = Join-Path -Path $Path -ChildPath $folder
if (Test-Path -LiteralPath $target) {
Write-Verbose "Exists, skipping: $target"
$skipped++
continue
}
if ($PSCmdlet.ShouldProcess($target, 'Create directory')) {
try {
New-Item -ItemType Directory -Path $target -ErrorAction Stop | Out-Null
Write-Host "Created: $target" -ForegroundColor Green
$created++
}
catch {
Write-Warning "Failed to create '$target': $($_.Exception.Message)"
$failed++
}
}
}
Write-Host "`nDone. Created: $created | Skipped (already existed): $skipped | Failed: $failed"
}