I want to get a list of files that don't have a filename extension. Consider the content of my directory to be:
folder
file1
file2.mp4
My goal would be to get file1
only.
Running Get-ChildItem -Exclude *.* -File
returned nothing.
Running Get-ChildItem -Exclude *.*
returned folder
and file1
.
Running Get-ChildItem -File
returned file1
and file2.mp4
.
Any idea if there is any way of using Get-ChildItem to only return file1
?
In PowerShell v3+ (including PowerShell (Core) 7):
Get-ChildItem -File -Filter *.
-File
limits output to just files (as opposed to directories).
-Filter *.
selects only those files that have no extension.
-Filter
is generally preferable to -Include
/ -Exclude
for performance reasons, because it filters at the source, rather than returning all objects and letting PowerShell do the filtering.
In PSv2, where the -File
switch isn't available, you need an additional Where-Object
call to limit the results to files, as TheIncorrigible1 points out:
Get-ChildItem -Filter *. | Where-Object { -not $_.PSIsContainer }
Slower PowerShell (Core) 7 solution:
Get-ChildItem -File | Where-Object -Not Extension
Optional background information:
That a -Filter
argument is processed by the underlying provider, means that its behavior may differ from PowerShell's native capabilities, which is indeed the case here: the FileSystem
provider uses the Windows API's wildcard-expression matching, which has fewer features than PowerShell's wildcards as well as some historical quirks; also, it is limited to a single wildcard expression, whereas -Include
/ -Exclude
support multiple ones (separated with ,
).
Here, however, -Filter
offers something that PowerShell's wildcard matching doesn't: using *.
to match files / directories without extension.
-Include
/ -Exclude
generally offer functional advantages at the expense of performance, but they have their own limitations and quirks:
*.
isn't supported to match items without extension in PowerShell's wildcard expressions.
-Include
/ -Exclude
operate on the last component of the specified or implied path, so if you're implicitly targeting the current directory, they apply to that directory path, not to the individual files inside the directory.
Specifying -Recurse
changes that, but that searches the entire directory subtree.
While you should be able to add -Depth 0
to limit matches to the immediate child items while still being able to apply -Include
/ -Exclude
, this is broken in Windows PowerShell: The -Depth
argument is ignored in this case.
This problem has been fixed in PowerShell (Core) 7, however.
In short: -Include
/ -Exclude
offer no solution here.