Function Get-Tree
{
[CmdletBinding(DefaultParameterSetName =
'Path')]
param(
[Parameter(ParameterSetName
=
'Path',
Position=0,
ValueFromPipeline=$true,
ValueFromPipelineByPropertyName=$true)]
[string[]]
${Path}
=
$pwd,
[switch]
$showEmptyFolders,
[validateset("Default","Name","Extension",
"LastWriteTime",
"CreationTime",
"Length")]
[string]
$sortby
=
"Default",
[switch]
$descending,
[Parameter(ParameterSetName='LiteralItems',
Mandatory=$true,
ValueFromPipelineByPropertyName=$true)][Alias('PSPath')]
[string[]]${LiteralPath},
[Parameter(Position=1)]
[string] ${Filter},
[Parameter(Position=2)]
[string] ${regex},
[string[]] ${Include},
[string[]] ${Exclude},
[switch] ${Force},
[string]
$pretext
=
"",
[switch]
$nonfirst
)
process{
[void]$PSBoundParameters.Remove("Pretext")
[void]$PSBoundParameters.Remove("SortBy")
[void]$PSBoundParameters.Remove("showEmptyFolders")
[void]$PSBoundParameters.Remove("Descending")
if($sortby -ne
"Default"){
$sorting
=
{end{$input
|
Sort-Object
-Property
@{e={$_.$sortby}
; descending = $descending},@{e={$_.Name}}
-Descending:$descending}}
}
else{
$sorting
=
{end{$input}}
}
$fe = $ie =
$false
[void]$PSBoundParameters.Remove("regex")
[void]$PSBoundParameters.Remove("nonfirst")
if($PSBoundParameters.Remove("filter")){
$fe
=
$true
}
else{
$Filter
=
"*"
}
if($PSBoundParameters.Remove("include")){
$ie
=
$true
}
else{
$Include
=
@("*")
}
if($sortby -eq
'default'
-and
$descending){
$items
=
@(Get-ChildItem
@PSBoundParameters
-File)
+
@(Get-ChildItem
-Path
$path
-Directory)
}
else{
$items
=
@(Get-ChildItem
-Path
$path
-Directory
-erroraction
ignore)
+
@(Get-ChildItem
@PSBoundParameters
-File
-erroraction
ignore)
}
$items = $items |
Where-Object
{$o
=
$_
; $o.psiscontainer
-or
($o.name
-like
$Filter
-and
(($Include
|
?{$o.name
-like
$_})
-and
$o.name
-match
$regex))}
|
&$sorting
if(!$nonfirst){
$tempitem
=
Get-Item
-Path
$items[0].fullname
if($tempitem.psiscontainer){
$item
=
$items[0].Parent
}
else{
$item
=
$items[0].Directory
}
Add-Member
-InputObject
$item
-MemberType
NoteProperty
-Name
Tree
-Value
"📂$($item.fullname)"
-TypeName
FileWithTree
-PassThru
}
if($items){
$char
=
"└"
$currentout
=
[collections.arraylist]
@()
for($i
=
$items.count
-1;
$i
-ge
0;
$i--){
Add-Member
-InputObject
$items[$i]
-MemberType
NoteProperty
-Name
Pretext
-Value
($pretext
+
$char
+
"───")
-TypeName
FileWithTree
if(!$items[$i].psiscontainer){
$result
=
$items[$i]
[void]
$currentout.Insert(0,$items[$i])
Add-Member
-InputObject
$items[$i]
-MemberType
NoteProperty
-Name
Tree
-Value
($pretext
+
$char
+
"───"
+
$items[$i].name)
}
else{
[void]
$PSBoundParameters.Remove("path")
if($fe){
$PSBoundParameters.filter
=
$Filter
}
if($ie){
$PSBoundParameters.include
=
$Include
}
$newpretext
=
$items[$i].Pretext
-replace
"├",
"│"
-replace
"[─└]",
"
"
$result
=
Get-Tree
-path
$items[$i].fullname
-sortby
$sortby
-descending:$descending
-pretext
$newpretext
@PSBoundParameters
-regex
$regex
-nonfirst
-showEmptyFolders:$showEmptyFolders
if($showEmptyFolders
-or
$result){
if($result -is
[collections.ilist]){
$currentout.InsertRange(0,$result)
}
else{
[void] $currentout.Insert(0,$result)
}
Add-Member -InputObject
$items[$i]
-MemberType
NoteProperty
-Name
Tree
-Value
($pretext
+
$char
+
"───"
+
"📂$($items[$i].name)")
[void] $currentout.Insert(0,$items[$i])
}
}
if($showEmptyFolders
-or
$result){
$char
=
"├"
}
}
$currentout
}
}
}
Update-FormatData
-AppendPath
$PSScriptRoot\FileTreeView.Format.ps1xml
<?xml
version="1.0"
encoding="utf-8"
?>
<Configuration>
<SelectionSets>
<SelectionSet>
<Name>FileWithTreeSet</Name>
<Types>
<TypeName>FileWithTree</TypeName>
</Types>
</SelectionSet>
</SelectionSets>
<!-- ################
GLOBAL CONTROL DEFINITIONS ################ -->
<Controls>
<Control>
<Name>FileSystemTypes-GroupingFormat</Name>
<CustomControl>
<CustomEntries>
<CustomEntry>
<CustomItem>
<Frame>
<LeftIndent>4</LeftIndent>
<CustomItem>
<Text
AssemblyName="System.Management.Automation"
BaseName="FileSystemProviderStrings"
ResourceId="DirectoryDisplayGrouping"/>
<ExpressionBinding>
<ScriptBlock>
$_.PSParentPath.Replace("Microsoft.PowerShell.Core\FileSystem::",
"")
</ScriptBlock>
</ExpressionBinding>
<NewLine/>
</CustomItem>
</Frame>
</CustomItem>
</CustomEntry>
</CustomEntries>
</CustomControl>
</Control>
</Controls>
<!-- ################
VIEW DEFINITIONS ################ -->
<ViewDefinitions>
<View>
<Name>children</Name>
<ViewSelectedBy>
<SelectionSetName>FileWithTreeSet</SelectionSetName>
</ViewSelectedBy>
<TableControl>
<TableHeaders>
<TableColumnHeader>
<Label>Mode</Label>
<Width>7</Width>
<Alignment>left</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>LastWriteTime</Label>
<Width>25</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader>
<Label>Length</Label>
<Width>14</Width>
<Alignment>right</Alignment>
</TableColumnHeader>
<TableColumnHeader/>
</TableHeaders>
<TableRowEntries>
<TableRowEntry>
<Wrap/>
<TableColumnItems>
<TableColumnItem>
<PropertyName>Mode</PropertyName>
</TableColumnItem>
<TableColumnItem>
<ScriptBlock>
[String]::Format("{0,10}
{1,8}", $_.LastWriteTime.ToString("d"),
$_.LastWriteTime.ToString("t"))
</ScriptBlock>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Length</PropertyName>
</TableColumnItem>
<TableColumnItem>
<PropertyName>Tree</PropertyName>
</TableColumnItem>
</TableColumnItems>
</TableRowEntry>
</TableRowEntries>
</TableControl>
</View>
</ViewDefinitions>
</Configuration>