问题
I have a list in my C: directory that has many files. If I try to run an -Exclude on it, I get no returns. Same with -Include. If I use filter it returns what I expected to get back. Am I not understanding what it should be doing?
Here is an example of what I am running and getting nothing:
Get-ChildItem -Path C: -Exclude "*.txt"
I get nothing back. If I run
Get-Childitem -filter "*.txt"
I get this back:
Mode LastWriteTime Length Name
---- ------------- ------ ----
-a---- 11/7/2007 8:00 AM 17734 eula.1028.txt
-a---- 11/7/2007 8:00 AM 17734 eula.1031.txt
-a---- 11/7/2007 8:00 AM 10134 eula.1033.txt
-a---- 11/7/2007 8:00 AM 17734 eula.1036.txt
-a---- 11/7/2007 8:00 AM 17734 eula.1040.txt
-a---- 11/7/2007 8:00 AM 118 eula.1041.txt
-a---- 11/7/2007 8:00 AM 17734 eula.1042.txt
-a---- 11/7/2007 8:00 AM 17734 eula.2052.txt
-a---- 11/7/2007 8:00 AM 17734 eula.3082.txt
7/7/2016 8:50 AM 93 HaxLogs.txt
-a---- 7/8/2016 8:30 AM 0 Test.txt
回答1:
Get-ChildItem -Path "C:\*" -Include "*.txt"
This example, of how -Include should work, will give you the results you were expecting. Note that I provided a wildcard in the path parameter as well, to explicitly define the path as "any file in the root C:" as opposed to "C:" itself.
Source: https://technet.microsoft.com/library/hh849800.aspx
Example 3 from this link, in case it goes defunct (note the wildcard in path here, as well):
C:\> Get-ChildItem –Path "C:\Windows\Logs\*" -Include "*.txt" -Exclude "A*"
回答2:
To summarize and complement gravity's and Brian Reynolds's helpful answers:
There are two distinct problems with your approach:
Targeting
C:probably doesn't (always) do what you want, becauseC:refers to whatever happens to be the current location (working dir.) on drive C: at the moment.- To target the root folder of drive C:, you must use
C:\, which I'll assume is what you meant in the remainder of this answer.
- To target the root folder of drive C:, you must use
Using the
-Exclude(and also-Include) parameter with neither-Recursenor a-Pathvalue ending in\*often yields NO results. Unexpected? Indeed - see below for more.- Thus,
Get-Item -Path C:\* -Exclude *.txt- note the switch fromGet-ChildItemtoGet-Itemand the*afterC:\- is needed to make your command work for the items located directly inC:\only.
- Thus,
Background information:
Using the provider-native -Filter parameter is generally preferable to -Include, because:
it is much faster than
-Includedue to the provider itself performing the filtering at the source, as opposed to letting PowerShell apply the filter later, after all objects have been received.it doesn't require you to switch to
Get-Itemand append\*to the-Pathparameter value.Get-ChildItem -Path C:\ -Filter *.txtworks fine for matching all*.txtfiles in the root directory of C:, for instance.
That said, there are Caveats:
The wildcard pattern language supported by
-Filterhas fewer features than PowerShell's and may unexpectedly match short (8.3) filenames - see this well-researched answer for the gory details.-Filtersupports only a single pattern, whereas-Includesupports multiple ones (an array of patterns).
Unfortunately, -Filter is always a positive (inclusionary) filter and therefore cannot be used to provide the functionality of -Exclude.
The implementation of -Include / -Exclude with Get-ChildItem is unintuitive and has pitfalls:
Side note: if you only use one -Include pattern (as opposed to -Exclude), it's easier to append the pattern directly to the -Path argument; e.g.: Get-ChildItem C:\*.txt
tl;dr: To get predictable behavior with -Include / -Exclude, use Get-Item C:\path\to\* (note the appended \* and the switch from Get-*Child*Item) - unless you also use -Recurse.
-Includeand-Excludedo not work as one would intuitively expect:-Includeand-Excludemodify the leaf (last) path component of the-Pathargument.That means that the patterns are applied to the leaf component of the folder path itself first, before getting applied to the child items, if at all.
If the input path doesn't end in
\*and-Recurseis not specified, the implications are as follows:-Include: If the input path's last path component does not match the-Includepattern(s), the input path itself is excluded (not included), and the path's child items are never looked at - nothing is output.-Exclude: Analogously, if the input path's last path component does match the-Excludepattern(s), the input path itself is excluded, and the path's child items are never looked at - nothing is output.- In the special case of path
C:\(Get-ChildItem -Path C:\ -Exclude <any-pattern>), where arguably the last path component is the empty string, it seems that any exclusion pattern is considered a match, and no output is ever produced.
- In the special case of path
As stated, the problem doesn't surface if
-Recurseis used, because that forces descending into the input path's subtree, even if the input path itself is not included / excluded.
Unless
-Recurseis needed, the only way to get expected behavior is to replaceGet-ChildItem C:\path\to -Include / -ExcludewithGet-Item C:\path\to\* -Include / -Exclude- note the use ofGet-Iteminstead ofGet-ChildItem, and that\*was appended to the-Pathargument.- By contrast, if you use
Get-ChildItemand there are directories among the matches,Get-ChildItemwill output their contents instead.
- By contrast, if you use
With
-LiteralPathrather than-Path,-Includeand-Excludeare quietly ignored - they have no effect whatsoever.
Examples: problematic uses of -Include / -Exclude
Note: To make all commands below work as one would intuitively expect, replace Get-ChildItem C:\Windows with Get-Item C:\Windows\* - note the use of a different cmdlet, Get-Item, and the appended \*.
# HAPPENS TO WORK, BUT IS NOT ROBUST:
# Matches all w* items *inside* C:\Windows, but
# ONLY because w* happens to match 'Windows' - the last input
# path component - too.
Get-ChildItem C:\Windows -Include w*
# HAPPENS TO WORK, BUT IS NOT ROBUST:
# Matches all items whose names *don't* start with a-v *inside* C:\Windows, but
# ONLY because [a-v]* happens not to exclude 'Windows' - the last input
# path component - too.
Get-ChildItem C:\Windows -Exclude [a-v]*
# OUTPUTS NOTHING:
# Because t* doesn't match 'Windows', the child items of
# 'C:\Windows' are not considered.
Get-ChildItem C:\Windows -Include t*
# OUTPUTS NOTHING:
# Because w* matches 'Windows', it is excluded, and
# the child items of 'C:\Windows' are not considered.
Get-ChildItem C:\Windows -Exclude w*
回答3:
Using 'C:' with no slash after it is the reason you're not getting the results you want. This is being interpreted as a relative path to the current directory instead of the root of the C drive. (See: Path with no slash after drive letter and colon - what does it point to?)
If you use 'C:\' instead it should work as expected.
Edit: My mistake; I was responding specifically to the examples which only use '-exclude'.
来源:https://stackoverflow.com/questions/38269209/using-get-childitem-exclude-or-include-returns-nothing