-Filter only accepts a single pattern.
Use -Include and -Exclude instead[1], both of which accept multiple patterns.
# Two inclusion patterns
Get-ChildItem -Recurse -Path $sourcePathPDF -Include *.pdf, *sold*
# One inclusion, one exclusion pattern.
Get-ChildItem -Recurse -Path $sourcePathPDF -Include *.pdf -Exclude *Sold*
Note:
As of PowerShell 7.2, -Include and -Exclude are hampered by performance problems, as Mathias R. Jessen notes, due to their inefficient implementation (see GitHub issue #8662), so the Where-Object-based solution discussed below may be called for not just for more complex matching logic, but for performance alone.
-Include and -Exclude use PowerShell's wildcard expressions, which have more features and lack the legacy quirks of the platform-native patterns that -Filter supports - see this answer for more information.
- The upside of using
-Filter is that its much faster than -Include / -Exclude, because -Filter filters _at the source, whereas -Include / -Exclude filters are applied after the fact, by PowerShell, after all items have been retrieved first.
Without -Recurse, -Include and -Exclude do not work as expected - use Get-Item * -Include/-Exclude ... instead - see this answer.
For more sophisticated pattern matching and/or better performance, pipe to a Where-Object call in whose script block you can use the wildcard-based -like operator, as Mathias recommends; alternatively, for even more flexible matching, you can use the regex-based -match operator. To adapt Mathias' -like-based Where-Object solution from the comment:
Get-ChildItem -Recurse -Path $sourcePathPDF |
Where-Object { $_.Name -like '*.pdf' -and $_.Name -notlike '*Sold*' }
For (currently) best performance you can pre-filter with -Filter:
Get-ChildItem -Recurse -Path $sourcePathPDF -Filter *.pdf |
Where-Object { $_.Name -notlike '*Sold*' }
As for what you tried:
-Filter, -Include, and -Exclude are string-typed - there is no support for passing script blocks ({ ... } with arbitrary expression to them.
- While pipeline-binding parameters may accept script blocks, in order to supply parameter values dynamically, based on the input object at hand (a feature known as delay-bind script blocks), neither of these parameters support such binding, so passing script blocks doesn't apply.
What actually happened in your attempt is that the stringified version of script block {-filter '*.pdf' -and '*Sold*'} - which is its verbatim content (excluding { and }) - was positionally bound to the -Filter parameter.
- That is, you effectively passed
-Filter "-filter '*.pdf' -and '*Sold*'", which predictably didn't match any files, because verbatim -filter '*.pdf' -and '*Sold*' was used as the pattern.
[1] Note that you may even combine -Filter with -Include / -Exclude, in which case the -Filter argument is applied first, at the source. Because of how -Include and -Exclude currently work, this is only works meaningfully if the input path ends in \* or -Recurse is used - see this answer.