I wrapped Get-ChildItem
in a generic function to add checks and be able to re-use it. When combining -File
with -Exclude
, the function seems to break even though the same call to Get-ChildItem
outside of it does work as expected.
What is going wrong? How can I fix it?
Get-ChildItem Exclude and File parameters don't work together
function Get-Object {
[CmdletBinding ()]
param (
[Parameter (
Position = 1,
Mandatory = $true,
HelpMessage = "Path to the object"
)]
[String]
$Path,
[Parameter (
Position = 2,
Mandatory = $false,
HelpMessage = "Type of object"
)]
[ValidateSet ("All", "File", "Folder")]
[String]
$Type = "All",
[Parameter (
Position = 3,
Mandatory = $false,
HelpMessage = "Filter to apply"
)]
[String]
$Filter = "*",
[Parameter (
Position = 4,
Mandatory = $false,
HelpMessage = "Pattern to exclude"
)]
[String]
$Exclude = $null
)
begin {
if (-Not (Test-Path -Path $Path)) {
Write-Host "$Path does not exists."
exit 1
}
$ObjectType = [ordered]@{
"All" = "items"
"File" = "files"
"Folder" = "folders"
}
}
process {
# Get files
switch ($Type) {
"File" {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude -File
}
"Folder" {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude -Directory
}
default {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude
}
}
# If no files are found, print hints
if ($Files.Count -eq 0) {
if ($Filter -ne "*") {
Write-Host "No $($ObjectType[$Type]) were found in $Path matching the filter ""$Filter""."
} elseif ($Exclude) {
Write-Host "No $($ObjectType[$Type]) corresponding to the criterias were found in $Path."
} else {
Write-Host "No $($ObjectType[$Type]) were found in $Path."
}
# exit 1
} else {
return $Files
}
}
}
$Path = Split-Path -Path $MyInvocation.MyCommand.Definition
$RelativePath = "\test"
$AbsolutePath = Join-Path -Path $Path -ChildPath $RelativePath
$Filter = "*"
$Exclude = $null
Get-ChildItem -Path $RelativePath -Filter $Filter -Exclude $Exclude -File
Get-ChildItem -Path $AbsolutePath -Filter $Filter -Exclude $Exclude -File
Get-Object -Path $RelativePath -Filter $Filter -Exclude $Exclude -Type "File"
Get-Object -Path $AbsolutePath -Filter $Filter -Exclude $Exclude -Type "File"
PS C:\> .\test.ps1
Directory: C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 21/09/2018 18:42 0 text.txt
-a---- 21/09/2018 18:42 0 text.txt
No files were found in \test.
No files were found in C:\test.
PS: Any constructive criticism on syntax/best practices is welcome.
This seems to be a known problem as per this issue on the PowerShell GIT repository.
There appear to be a conflict while using -Filter
, -Exclude
, and -File
all at the same time. By removing one or adding -Recurse
, the function works as expected.
Get-ChildItem -Path $Path -Filter $Filter -File
Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude -File -Recurse
Obviously this is not optimal and should be considered as a workaround until the issue is fixed.
function Get-Object {
[CmdletBinding ()]
param (
[Parameter (
Position = 1,
Mandatory = $true,
HelpMessage = "Path to the items"
)]
[String]
$Path,
[Parameter (
Position = 2,
Mandatory = $false,
HelpMessage = "Type of object"
)]
[ValidateSet ("All", "File", "Folder")]
[String]
$Type = "All",
[Parameter (
Position = 3,
Mandatory = $false,
HelpMessage = "Filter to apply"
)]
[String]
$Filter = "*",
[Parameter (
Position = 4,
Mandatory = $false,
HelpMessage = "Pattern to exclude"
)]
[String]
$Exclude = $null
)
begin {
if (-Not (Test-Path -Path $Path)) {
Write-Host "$Path does not exists."
exit 1
}
$ObjectType = [ordered]@{
"All" = "items"
"File" = "files"
"Folder" = "folders"
}
}
process {
# Get files
switch ($Type) {
"File" {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude -File -Recurse
}
"Folder" {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude -Directory
}
default {
$Files = Get-ChildItem -Path $Path -Filter $Filter -Exclude $Exclude
}
}
# If no files are found, print hints
if ($Files.Count -eq 0) {
if ($Filter -ne "*") {
Write-Host "No $($ObjectType[$Type]) were found in $Path matching the filter ""$Filter""."
} elseif ($Exclude) {
Write-Host "No $($ObjectType[$Type]) corresponding to the criterias were found in $Path."
} else {
Write-Host "No $($ObjectType[$Type]) were found in $Path."
}
# exit 1
} else {
return $Files
}
}
}
$Path = Split-Path -Path $MyInvocation.MyCommand.Definition
$RelativePath = "\test"
$AbsolutePath = Join-Path -Path $Path -ChildPath $RelativePath
$Filter = "*"
$Exclude = $null
Get-ChildItem -Path $RelativePath -Filter $Filter -Exclude $Exclude -File
Get-ChildItem -Path $AbsolutePath -Filter $Filter -Exclude $Exclude -File
Get-Object -Path $RelativePath -Filter $Filter -Exclude $Exclude -Type "File"
Get-Object -Path $AbsolutePath -Filter $Filter -Exclude $Exclude -Type "File"
PS C:\> .\test.ps1
Directory: C:\test
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 21/09/2018 18:42 0 text.txt
-a---- 21/09/2018 18:42 0 text.txt
-a---- 21/09/2018 18:42 0 text.txt
-a---- 21/09/2018 18:42 0 text.txt