Skip to content

Commit

Permalink
Merge pull request #26 from santisq/25-add-include-parameter
Browse files Browse the repository at this point in the history
25 add include parameter
  • Loading branch information
santisq committed Oct 6, 2023
2 parents 7238b44 + a87b92a commit 31e17cd
Show file tree
Hide file tree
Showing 7 changed files with 167 additions and 24 deletions.
3 changes: 3 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
# CHANGELOG

- __10/05/2023__
- Added Parameter `-Include`. Works very similar to `-Exclude`, the patterns are evaluated against the items `.FullName` property, however this parameter targets only files (`FileInfo` instances).

- __09/11/2023__
- No changes to the cmdlet but a few improvements to the code base:
- [x] <https://github.com/santisq/PSTree/issues/16> `PSTreeCache` and `PSTreeIndexer` internal classes have been sealed following the recommendations from dotnet/runtime#49944.
Expand Down
39 changes: 39 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,45 @@ d---- 10.30 KB │ └── PSTree
-a--- 619.00 B │ ├── PSTreeIndexer.cs
```

### Include `.ps1` and `.cs` files and exclude some folders

```powershell
PS ..\PSTree> Get-PStree -Include *.ps1, *.cs -Exclude *output, *tools, *docs, *module
Source: C:\path\to\PSTree
Mode Length Hierarchy
---- ------ ---------
d---- 33.15 KB PSTree
-a--- 2.35 KB ├── build.ps1
-a--- 8.10 KB ├── PSTree.build.ps1
d---- 13.29 KB ├── tests
-a--- 765.00 B │ ├── FormattingInternals.tests.ps1
-a--- 5.89 KB │ ├── GetPSTreeCommand.tests.ps1
-a--- 1.51 KB │ ├── PathExtensions.tests.ps1
-a--- 1.38 KB │ ├── PSTreeDirectory.ps1
-a--- 920.00 B │ ├── PSTreeFile.tests.ps1
-a--- 2.09 KB │ └── PSTreeFileSystemInfo_T.tests.ps1
d---- 0.00 B ├── src
d---- 12.15 KB │ └── PSTree
-a--- 931.00 B │ ├── ExceptionHelpers.cs
-a--- 4.09 KB │ ├── PathExtensions.cs
-a--- 900.00 B │ ├── PSTreeCache.cs
-a--- 1.06 KB │ ├── PSTreeDirectory.cs
-a--- 1.66 KB │ ├── PSTreeExtensions.cs
-a--- 517.00 B │ ├── PSTreeFile.cs
-a--- 399.00 B │ ├── PSTreeFileSystemInfo.cs
-a--- 1.61 KB │ ├── PSTreeFileSystemInfo_T.cs
-a--- 626.00 B │ ├── PSTreeIndexer.cs
d---- 16.53 KB │ ├── obj
d---- 1.15 KB │ ├── Internal
d---- 6.43 KB │ ├── Commands
d---- 0.00 B │ └── bin
d---- 4.07 KB ├── .vscode
d---- 0.00 B └── .github
d---- 4.17 KB └── workflows
```

### Get the `src` tree recursively displaying only folders

```powershell
Expand Down
71 changes: 61 additions & 10 deletions docs/en-US/Get-PSTree.md
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,31 @@ schema: 2.0.0
### Path (Default)

```powershell
Get-PSTree [-Path <String[]>] [-Recurse] [-Force] [-Directory] [-RecursiveSize] [-Exclude <String[]>]
[-Depth <UInt32>] [<CommonParameters>]
Get-PSTree
[[-Path] <String[]>]
[-Depth <UInt32>]
[-Recurse]
[-Force]
[-Directory]
[-RecursiveSize]
[-Exclude <String[]>]
[-Include <String[]>]
[<CommonParameters>]
```

### LiteralPath

```powershell
Get-PSTree [[-LiteralPath] <String[]>] [-Recurse] [-Force] [-Directory] [-RecursiveSize] [-Exclude <String[]>]
[-Depth <UInt32>] [<CommonParameters>]
Get-PSTree
[-LiteralPath <String[]>]
[-Depth <UInt32>]
[-Recurse]
[-Force]
[-Directory]
[-RecursiveSize]
[-Exclude <String[]>]
[-Include <String[]>]
[<CommonParameters>]
```

## DESCRIPTION
Expand All @@ -41,44 +57,52 @@ PS ..\PSTree> Get-PSTree

The default parameter set uses `-Depth` with a value of 3. No hidden and system files folder are displayed and recursive folder size is not calculated.

### Example 2: Get the hierarchy of the `$HOME` directory recursively displaying only folders
### Example 2: Get the `$HOME` tree recursively displaying only folders

```powershell
PS ..\PSTree> Get-PSTree $HOME -Directory -Recurse
```

In this example `$HOME` is bound positionally to the `-Path` parameter.

### Example 3: Recurse `$HOME` subdirectories 2 levels deep displaying hidden files and folders
### Example 3: Get the `$HOME` tree 2 levels deep displaying hidden files and folders

```powershell
PS ..\PSTree> Get-PSTree -Depth 2 -Force
```

The `-Force` switch is needed to display hidden files and folders. In addition, hidden child items do not add up to the folders size without this switch.

### Example 4: Recurse the `C:\` drive 2 levels in depth displaying only folders with their recursive size
### Example 4: Get the `C:\` drive tree 2 levels in depth displaying only folders calculating the recursive size

```powershell
PS ..\PSTree> Get-PSTree C:\ -Depth 2 -RecursiveSize -Directory
```

### Example 5: Get the `$HOME` directory hierarchy recursively excluding all `.jpg` and `.png` files
### Example 5: Get the `$HOME` tree recursively excluding all `.jpg` and `.png` files

```powershell
PS ..\PSTree> Get-PSTree $HOME -Recurse -Exclude *.jpg, *.png
```

The `-Exclude` parameter supports [wildcard patterns](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_wildcards?view=powershell-7.3), exclusion patterns are tested against the items `.FullName` property. Excluded items do not do not add to the folders size.

### Example 6: Get the hierarchy of all folders in a location
### Example 6: Get the tree of all folders in a location

```powershell
PS ..\PSTree> Get-ChildItem -Directory | Get-PSTree
```

`DirectoryInfo` and `FileInfo` instances having the `PSPath` Property are bound to the `-LiteralPath` parameter.

### Example 7: Get the tree of all folders in a location including only `*.ps1` files

```powershell
PS ..\PSTree> Get-ChildItem -Directory | Get-PSTree -Include *.ps1
```

Similar to `-Exclude`, the `-Include` parameter supports [wildcard patterns](https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_wildcards?view=powershell-7.3), however, __this parameter works only with Files__.

## PARAMETERS

### -Depth
Expand Down Expand Up @@ -121,7 +145,10 @@ Wildcard characters are accepted.
Excluded items do not add to the recursive folders size.
> __NOTE__: Patterns are tested against the object's `.FullName` property.
> __NOTE__:
>
> - Patterns are tested against the object's `.FullName` property.
> - The `-Include` and `-Exclude` parameters can be used together and the inclusions are applied after the exclusions.

```yaml
Type: String[]
Expand Down Expand Up @@ -151,6 +178,30 @@ Accept pipeline input: False
Accept wildcard characters: False
```

### -Include

Specifies an array of one or more string patterns to be matched as the cmdlet gets child items.
Any matching item is included in the output.
Wildcard characters are accepted.

> __NOTE__:
>
> - Patterns are tested against the object's `.FullName` property.
> - This parameter focuses only on files, the inclusion patterns are only evaluated against `FileInfo` instances.
> - The `-Include` and `-Exclude` parameters can be used together and the inclusions are applied after the exclusions.

```yaml
Type: String[]
Parameter Sets: (All)
Aliases:
Required: False
Position: Named
Default value: None
Accept pipeline input: False
Accept wildcard characters: True
```

### -LiteralPath

Absolute or relative folder path.
Expand Down
4 changes: 2 additions & 2 deletions module/PSTree.psd1
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
RootModule = 'bin/netstandard2.0/PSTree.dll'

# Version number of this module.
ModuleVersion = '2.1.14'
ModuleVersion = '2.1.15'

# Supported PSEditions
# CompatiblePSEditions = @()
Expand All @@ -29,7 +29,7 @@
Copyright = '(c) Santiago Squarzon. All rights reserved.'

# Description of the functionality provided by this module
Description = 'tree like function for PowerShell'
Description = 'tree like cmdlet for PowerShell'

# Minimum version of the PowerShell engine required by this module
PowerShellVersion = '5.1'
Expand Down
58 changes: 48 additions & 10 deletions src/PSTree/Commands/GetPSTreeCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,10 +15,14 @@ public sealed class GetPSTreeCommand : PSCmdlet

private bool _withExclude;

private bool _withInclude;

private string[]? _paths;

private WildcardPattern[]? _excludePatterns;

private WildcardPattern[]? _includePatterns;

private readonly PSTreeIndexer _indexer = new();

private readonly Stack<PSTreeDirectory> _stack = new();
Expand Down Expand Up @@ -78,26 +82,42 @@ public string[]? LiteralPath
[ValidateNotNullOrEmpty]
public string[]? Exclude { get; set; }

[Parameter]
[SupportsWildcards]
[ValidateNotNullOrEmpty]
public string[]? Include { get; set; }

protected override void BeginProcessing()
{
if (Recurse.IsPresent && !MyInvocation.BoundParameters.ContainsKey("Depth"))
{
Depth = int.MaxValue;
}

const WildcardOptions wpoptions =
WildcardOptions.Compiled
| WildcardOptions.CultureInvariant
| WildcardOptions.IgnoreCase;

if (Exclude is not null)
{
const WildcardOptions wpoptions =
WildcardOptions.Compiled
| WildcardOptions.CultureInvariant
| WildcardOptions.IgnoreCase;

_excludePatterns = Exclude
.Select(e => new WildcardPattern(e, wpoptions))
.ToArray();

_withExclude = true;
}

// this Parameter only targets files, there is no reason to use it
// if -Directory is in use
if (Include is not null && !Directory.IsPresent)
{
_includePatterns = Include
.Select(e => new WildcardPattern(e, wpoptions))
.ToArray();

_withInclude = true;
}
}

protected override void ProcessRecord()
Expand Down Expand Up @@ -128,6 +148,27 @@ private PSTreeFileSystemInfo[] Traverse(
_cache.Clear();
_stack.Push(new PSTreeDirectory(directory, source));

bool ShouldInclude(FileInfo file)
{
if (!_withInclude)
{
return true;
}

return _includePatterns.Any(e => e.IsMatch(file.FullName));
}

bool ShouldExclude(FileSystemInfo item)
{
if (!_withExclude)
{
return false;
}

return _excludePatterns.Any(e => e.IsMatch(item.FullName));
}


while (_stack.Count > 0)
{
IEnumerable<FileSystemInfo> enumerator;
Expand All @@ -147,7 +188,7 @@ private PSTreeFileSystemInfo[] Traverse(
continue;
}

if (_withExclude && ShouldExclude(item))
if (ShouldExclude(item))
{
continue;
}
Expand All @@ -161,7 +202,7 @@ private PSTreeFileSystemInfo[] Traverse(
continue;
}

if (keepProcessing)
if (keepProcessing && ShouldInclude(file))
{
_cache.AddFile(file, level, source);
}
Expand Down Expand Up @@ -206,7 +247,4 @@ private PSTreeFileSystemInfo[] Traverse(

return _cache.GetTree();
}

private bool ShouldExclude(FileSystemInfo item) =>
_excludePatterns.Any(e => e.IsMatch(item.FullName));
}
4 changes: 2 additions & 2 deletions src/PSTree/PSTree.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@
<Nullable>enable</Nullable>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<AssemblyName>PSTree</AssemblyName>
<LangVersion>latest</LangVersion>
<LangVersion>preview</LangVersion>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="PowerShellStandard.Library" Version="5.1.1" PrivateAssets="all" />
</ItemGroup>

</Project>
</Project>
12 changes: 12 additions & 0 deletions tests/GetPSTreeCommand.tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,18 @@ Describe 'Get-PSTree' {
} | Should -Not -BeTrue
}

It 'Include childs with -Include parameter' {
$include = '*.ps1', '*.cs'
Get-PSTree $testPath -Include $include -Recurse | ForEach-Object {
[System.Linq.Enumerable]::Any(
[string[]] $include,
[System.Func[string, bool]] {
$_.FullName -like $args[0] -or $_ -is [PSTree.PSTreeDirectory]
}
)
} | Should -BeTrue
}

It 'Should prioritize -Depth if used together with -Recurse' {
$ref = (Get-ChildItem $testPath -Directory | Get-ChildItem -Recurse).FullName
Get-PSTree $testPath -Directory -Recurse -Depth 1 |
Expand Down

0 comments on commit 31e17cd

Please sign in to comment.