Browse Source

fix: reject a null -Filter of Get-ChildItem2 and document the dot of the pattern

The escape of brackets in the pattern read the filter before the pattern could reject it, so a null filter ended in a NullReferenceException. The parameter now rejects null with a validation error that names it; an empty filter still matches no item.

The cmdlet compares each name that the enumeration returns with the pattern again. The two disagree for *.*: the enumeration returns every item, as Get-ChildItem does, and the comparison drops the names without a dot, files and folders alike. A test pins this and reaches the branch that drops an item; the help says that a dot is an ordinary character.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: AI Assistant <ai@example.com>
pull/118/head
Raimund Andree 2 days ago
parent
commit
ae3078f99a
  1. 5
      CHANGELOG.md
  2. 2
      Docs/Cmdlets/Get-ChildItem2.md
  3. 1
      NTFSSecurity/ItemCmdlets/GetChildItem2.cs
  4. 4
      NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml
  5. 21
      Tests/ItemCmdlets.Tests.ps1

5
CHANGELOG.md

@ -132,7 +132,10 @@ The format is based on
removed every item. They now stop and write no error removed every item. They now stop and write no error
- Fix `Get-ChildItem2 -Filter`, which read a bracket as the start of a - Fix `Get-ChildItem2 -Filter`, which read a bracket as the start of a
character class, so that it did not return a file with brackets in its name, character class, so that it did not return a file with brackets in its name,
such as `Report[1].txt`, for that name; only `*` and `?` are wildcards such as `Report[1].txt`, for that name; only `*` and `?` are wildcards. A dot
is an ordinary character, so `*.*` returns only the names that contain a dot
(unlike `Get-ChildItem`), and a null `-Filter` is rejected as a parameter
error
- Fix `Get-Help`, which showed only the syntax: ship the help file - Fix `Get-Help`, which showed only the syntax: ship the help file
`en-US\NTFSSecurity.dll-Help.xml` generated from the cmdlet documentation, `en-US\NTFSSecurity.dll-Help.xml` generated from the cmdlet documentation,
including the links that `Get-Help -Online` opens, instead of the outdated including the links that `Get-Help -Online` opens, instead of the outdated

2
Docs/Cmdlets/Get-ChildItem2.md

@ -134,7 +134,7 @@ Accept wildcard characters: False
### -Filter ### -Filter
Specifies a name pattern that an item must match to be returned. The pattern supports the `*` and `?` wildcard characters, and the match ignores case; any other character, such as a bracket, stands for itself, so `Report[1].txt` returns the file of that name. The default value is `*`, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder. Specifies a name pattern that an item must match to be returned. The pattern supports the `*` and `?` wildcard characters, and the match ignores case; any other character stands for itself. A bracket is an ordinary character, so `Report[1].txt` returns the file of that name, and so is a dot, so `*.*` returns only the items whose names contain a dot, not every item as it does for `Get-ChildItem`. The default value is `*`, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder.
```yaml ```yaml
Type: String Type: String

1
NTFSSecurity/ItemCmdlets/GetChildItem2.cs

@ -45,6 +45,7 @@ namespace NTFSSecurity
} }
[Parameter(Position = 2)] [Parameter(Position = 2)]
[ValidateNotNull]
public string Filter public string Filter
{ {
get { return filter; } get { return filter; }

4
NTFSSecurity/en-US/NTFSSecurity.dll-Help.xml

@ -3520,7 +3520,7 @@ PS C:\&gt; Disable-Privileges</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none"> <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
<maml:name>Filter</maml:name> <maml:name>Filter</maml:name>
<maml:description> <maml:description>
<maml:para>Specifies a name pattern that an item must match to be returned. The pattern supports the ` ` and `?` wildcard characters, and the match ignores case; any other character, such as a bracket, stands for itself, so `Report[1].txt` returns the file of that name. The default value is ` `, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder.</maml:para> <maml:para>Specifies a name pattern that an item must match to be returned. The pattern supports the ` ` and `?` wildcard characters, and the match ignores case; any other character stands for itself. A bracket is an ordinary character, so `Report[1].txt` returns the file of that name, and so is a dot, so ` . ` returns only the items whose names contain a dot, not every item as it does for `Get-ChildItem`. The default value is ` `, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder.</maml:para>
</maml:description> </maml:description>
<command:parameterValue required="true" variableLength="false">String</command:parameterValue> <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
<dev:type> <dev:type>
@ -3724,7 +3724,7 @@ PS C:\&gt; Disable-Privileges</dev:code>
<command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none"> <command:parameter required="false" variableLength="true" globbing="false" pipelineInput="False" position="2" aliases="none">
<maml:name>Filter</maml:name> <maml:name>Filter</maml:name>
<maml:description> <maml:description>
<maml:para>Specifies a name pattern that an item must match to be returned. The pattern supports the ` ` and `?` wildcard characters, and the match ignores case; any other character, such as a bracket, stands for itself, so `Report[1].txt` returns the file of that name. The default value is ` `, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder.</maml:para> <maml:para>Specifies a name pattern that an item must match to be returned. The pattern supports the ` ` and `?` wildcard characters, and the match ignores case; any other character stands for itself. A bracket is an ordinary character, so `Report[1].txt` returns the file of that name, and so is a dot, so ` . ` returns only the items whose names contain a dot, not every item as it does for `Get-ChildItem`. The default value is ` `, which returns every item. The pattern is applied to the name of each item, not to its path, and during a recursive listing it restricts only the returned items; the cmdlet still descends into every subfolder.</maml:para>
</maml:description> </maml:description>
<command:parameterValue required="true" variableLength="false">String</command:parameterValue> <command:parameterValue required="true" variableLength="false">String</command:parameterValue>
<dev:type> <dev:type>

21
Tests/ItemCmdlets.Tests.ps1

@ -176,6 +176,27 @@ Describe 'Get-ChildItem2' {
$result[0].Name | Should -BeExactly 'Report[1].txt' $result[0].Name | Should -BeExactly 'Report[1].txt'
} }
# The dot is an ordinary character of the pattern, so *.* selects the names that contain a dot. The enumeration
# alone would return every item for it, as Get-ChildItem and cmd.exe do; the cmdlet then compares each name with
# the pattern and drops the items whose names have no dot, files and folders alike.
It 'Should return only the items with a dot in their names for -Filter *.*' {
$folder = New-TestSandboxItem -Sandbox $sandbox -Name 'FilterDot' -Directory
$paths = @('Page.htm', 'NoExtension', 'NoExtensionFolder') | ForEach-Object -Process { Join-Path -Path $folder -ChildPath $_ }
Assert-TestSandboxPath -Sandbox $sandbox -Path $paths
Set-Content -LiteralPath $paths[0] -Value 'Page'
Set-Content -LiteralPath $paths[1] -Value 'NoExtension'
New-Item -ItemType Directory -Path $paths[2] | Out-Null
$result = @(Get-ChildItem2 -Path $folder -Filter '*.*' -ErrorAction Stop)
($result.Name -join ',') | Should -BeExactly 'Page.htm'
}
It 'Should reject a null -Filter' {
{ Get-ChildItem2 -Path $tree -Filter $null -ErrorAction Stop } |
Should -Throw -ErrorId 'ParameterArgumentValidationError,NTFSSecurity.GetChildItem2' -ExpectedMessage "*'Filter'*"
}
It 'Should stop a recursive pipeline without recording an enumeration error' { It 'Should stop a recursive pipeline without recording an enumeration error' {
$result = @(Get-ChildItem2 -Path $tree -Recurse -ErrorVariable childErrors -ErrorAction SilentlyContinue | Select-Object -First 1) $result = @(Get-ChildItem2 -Path $tree -Recurse -ErrorVariable childErrors -ErrorAction SilentlyContinue | Select-Object -First 1)

Loading…
Cancel
Save