Use -Include rather than -Filter, which makes the wildcard pattern work as intended:
Get-ChildItem -Path C:\Users\User\Downloads -Recurse -Include *.txt.*
Note: This matches files that have .txt. anywhere in the filename, including foo.txt.csv or "triple extensions" files such as foo.txt.txt.txt.
*.txt.txt would yield only filenames that end in .txt.txt, which would still include triple-or-more .txt-extension filenames.
Note that *.txt.txt would work with -Filter too.
While the -Filter parameter has one major advantage - it makes the underlying filesystem provider perform filtering at the source which makes it much faster - it has limitations and pitfalls:
The wildcard pattern language is more limited than PowerShell's own, with legacy quirks - see this excellent answer for background information.
- In essence, only
* and ? are supported (not also character set/range expressions such as [0-9]), and .* or just . at the end of a pattern match the empty string too (which is what you experienced).
- In Windows PowerShell (no longer a problem in PowerShell [Core] 6+), matching is unexpectedly also performed against the normally hidden short (8.3) filenames, which means that something like
*.xls unexpectedly behaves like *.xls* and also matches .xlsx files, for instance.
You can only pass a single wildcard pattern to -Filter, whereas -Include supports multiple.
On a side note, -Include and -Exclude have their quirks too. Here, -Include works as intended due to -Recurse; without -Recurse, you'd have to make your -Path value end in \* to make it work - see GitHub issue #3304.
Alternatively, if you need only a single wildcard pattern, you can get away with directly appending that pattern to the path - C:\Users\User\Downloads\*.txt.* - as demonstrated in Matt's helpful answer.
However, the caveat is that with -Recurse this only works as intended in PSv3 or above;
PSv2, by contrast, applies the pattern only to the immediate children (which was arguably the more sensible behavior).
On a related but distinct note, TessellatingHeckler has discovered an oddity when specifying literal paths that end in . chars. (present since at least PSv2 and still as of PSv5.1):
PS> Get-Item -LiteralPath c:\windows\system32\cmd.exe... | Format-List Name, Extension
Name : cmd.exe...
Extension : .exe
Note how (a) cmd.exe was still matched, despite the extraneous trailing . chars., and (b) the .Name property reflects those . chars. - even though neither .Extension nor .FullName do.
The issue has been reported here, but since the the cause is the legacy-bound behavior of the underlying GetFileAttributes native Windows API function, this issue will not be resolved in PowerShell.