DirwTools.psm1
|
function Format-FileSize { param ([long]$bytes) if ($bytes -ge 1GB) { "{0:N1} GB" -f ($bytes / 1GB) } elseif ($bytes -ge 1MB) { "{0:N1} MB" -f ($bytes / 1MB) } elseif ($bytes -ge 1KB) { "{0:N1} KB" -f ($bytes / 1KB) } else { "$bytes B" } } function Get-FolderSize { param ($folderPath) try { (Get-ChildItem -LiteralPath $folderPath -Recurse -Force -File -ErrorAction SilentlyContinue | Measure-Object -Property Length -Sum).Sum } catch { 0 } } function dirw { <# .SYNOPSIS Multi-column advanced DIR-like file listing for PowerShell. .DESCRIPTION Shows files and folders in multi-column format, like DIR /W, with color and (optional) file info. Supports sorting. .PARAMETER Target Folder or wildcard pattern (e.g. C:\Temp\*.txt). Default: current directory. .PARAMETER l Show sizes/dates (long format). .PARAMETER s Calculate folder sizes (recursive, slow on big dirs; implies -l). .PARAMETER a Show hidden files/directories. .PARAMETER sn Sort by name (default). .PARAMETER ss Sort by size. .PARAMETER sd Sort by date. .PARAMETER sortName Sort by name (long key). .PARAMETER sortSize Sort by size (long key). .PARAMETER sortDate Sort by date (long key). .PARAMETER oa Order ascending (default). .PARAMETER od Order descending. .PARAMETER orderAscending Order ascending (long key). .PARAMETER orderDescending Order descending (long key). .EXAMPLE dirw -l -a -ss -od dirw c:\temp\*.txt -ss .NOTES Author: Michael.Voitovich@gmail.com #> [CmdletBinding(PositionalBinding = $false)] param ( [Parameter(Position=0)] [string]$Target = ".", [switch]$l, [switch]$s, [switch]$a, [switch]$h, [switch]$long, [switch]$size, [switch]$all, [switch]$help, [switch]$sn, [switch]$ss, [switch]$sd, [switch]$sortName, [switch]$sortSize, [switch]$sortDate, [switch]$oa, [switch]$od, [switch]$orderAscending, [switch]$orderDescending ) if ($h -or $help) { Write-Host "Usage: dirw [path or pattern] [-l|-long] [-s|-size] [-a|-all] [-sn|-ss|-sd] [-oa|-od] [-h|-help]" -ForegroundColor Cyan Write-Host "" Write-Host "Options:" Write-Host " path/pattern Folder or wildcard pattern (default: . )" Write-Host " -l, -long Show sizes and dates (long format)" Write-Host " -s, -size Calculate size of folders (implies -l; may be slow on large folders)" Write-Host " -a, -all Show hidden files and folders" Write-Host " -sn, -sortName Sort by name (default)" Write-Host " -ss, -sortSize Sort by size" Write-Host " -sd, -sortDate Sort by date" Write-Host " -oa, -orderAscending Order ascending (default)" Write-Host " -od, -orderDescending Order descending" Write-Host " -h, -help Show this help" Write-Host "" Write-Host "Examples:" Write-Host " dirw" Write-Host " Show all files and folders in the current directory" Write-Host " dirw *.ps1 -sd -od" Write-Host " Show .ps1 files sorted by date, newest first" Write-Host " dirw C:\temp -l -ss" Write-Host " Show all files in C:\temp\ in long format, sorted by size (smallest to largest)" Write-Host " dirw C:\windows\*.exe -long -sortSize -a" Write-Host " Show all .exe files in C:\windows\ in long format, including hidden files" Write-Host " dirw C:\windows\ -s -a -od" Write-Host " Show all items in C:\windows\ (long format, folder sizes calculated, sorted largest to smallest, including hidden)" Write-Host "" return } $Long = $l -or $long $ShowHidden = $a -or $all $CalculateFolderSize = $s -or $size # Если -s или -size, обязательно включаем Long if ($CalculateFolderSize) { $Long = $true } # Определяем тип сортировки $SortBy = "Name" if ($ss -or $sortSize) { $SortBy = "Size" } elseif ($sd -or $sortDate) { $SortBy = "Date" } elseif ($sn -or $sortName) { $SortBy = "Name" } # Определяем направление сортировки $SortDescending = $false if ($od -or $orderDescending) { $SortDescending = $true } elseif ($oa -or $orderAscending) { $SortDescending = $false } if (-not $Target) { $Target = "." } $parentPath = (Split-Path $Target -Parent) if ($parentPath -and -not (Test-Path $parentPath)) { Write-Host "Path not found: $parentPath" -ForegroundColor Red return } $items = if ($ShowHidden) { Get-ChildItem -Path $Target -Force } else { Get-ChildItem -Path $Target | Where-Object { -not $_.Attributes.ToString().Contains("Hidden") } } if (-not $items) { Write-Host "(nothing found)" return } $execExtensions = @('.exe', '.bat', '.cmd', '.ps1', '.msi') # Сортировка if ($SortBy -eq "Size" -and $CalculateFolderSize) { foreach ($item in $items) { if ($item.PSIsContainer) { $item | Add-Member -NotePropertyName RealLength -NotePropertyValue (Get-FolderSize $item.FullName) } else { $item | Add-Member -NotePropertyName RealLength -NotePropertyValue $item.Length } } $items = if ($SortDescending) { $items | Sort-Object -Property RealLength -Descending } else { $items | Sort-Object -Property RealLength } } elseif ($SortBy -eq "Size") { $items = if ($SortDescending) { $items | Sort-Object -Property Length -Descending } else { $items | Sort-Object -Property Length } } elseif ($SortBy -eq "Date") { $items = if ($SortDescending) { $items | Sort-Object -Property LastWriteTime -Descending } else { $items | Sort-Object -Property LastWriteTime } } else { $items = if ($SortDescending) { $items | Sort-Object -Property Name -Descending } else { $items | Sort-Object -Property Name } } if ($Long) { $maxNameLength = ($items | ForEach-Object { $_.Name.Length } | Measure-Object -Maximum).Maximum $maxSizeLength = 10 $maxDateLength = 19 $rows = @() foreach ($item in $items) { $name = $item.Name.PadRight($maxNameLength) $color = "White" if ($item.PSIsContainer) { if ($CalculateFolderSize) { if ($item.PSObject.Properties["RealLength"]) { $folderBytes = $item.RealLength } else { $folderBytes = Get-FolderSize $item.FullName } $sizeVal = Format-FileSize($folderBytes) } else { $sizeVal = "<DIR>" } $color = "Yellow" } else { $sizeVal = Format-FileSize($item.Length) if ($execExtensions -contains $item.Extension.ToLower()) { $color = "Green" } } $sizeText = $sizeVal.PadLeft($maxSizeLength) $date = $item.LastWriteTime.ToString("yyyy-MM-dd HH:mm:ss") $rowText = "$name $sizeText $date" $rows += [PSCustomObject]@{ Text = $rowText; Color = $color } } $header = ("Name".PadRight($maxNameLength) + " " + "Size".PadLeft($maxSizeLength) + " " + "Modified") $maxRowLength = ($rows | ForEach-Object { $_.Text.Length } | Measure-Object -Maximum).Maximum $consoleWidth = [console]::WindowWidth $spacing = 6 $columnWidth = $maxRowLength + $spacing $columns = [Math]::Max(1, [Math]::Floor($consoleWidth / $columnWidth)) # Печатаем заголовок над каждой колонкой $headerLine = "" for ($c = 0; $c -lt $columns; $c++) { $headerLine += $header.PadRight($columnWidth) } Write-Host $headerLine -ForegroundColor Cyan # Выводим в несколько колонок for ($i = 0; $i -lt $rows.Count; $i += $columns) { for ($j = 0; $j -lt $columns; $j++) { $index = $i + $j if ($index -lt $rows.Count) { $row = $rows[$index] Write-Host -NoNewline $row.Text.PadRight($columnWidth) -ForegroundColor $row.Color } } Write-Host "" } } else { # краткий вывод в колонках $maxNameLength = ($items | ForEach-Object { $_.Name.Length } | Measure-Object -Maximum).Maximum $consoleWidth = [console]::WindowWidth $spacing = 2 $columnWidth = $maxNameLength + $spacing $columns = [Math]::Max(1, [Math]::Floor($consoleWidth / $columnWidth)) $i = 0 foreach ($item in $items) { $name = $item.Name $padded = $name.PadRight($columnWidth) if ($item.PSIsContainer) { $color = 'Yellow' } elseif ($execExtensions -contains $item.Extension.ToLower()) { $color = 'Green' } else { $color = 'White' } Write-Host -NoNewline $padded -ForegroundColor $color $i++ if ($i -ge $columns) { $i = 0 Write-Host "" } } if ($i -ne 0) { Write-Host "" } } Write-Host "" } Export-ModuleMember -Function dirw |