PetSerAl, as many times before, has provided the crucial pointer in a terse comment on the question (and he's also assisted in refining this answer):
$pathChildren = @(Get-ChildItem -Path $strPath)
The use of @(...)
, the array subexpression operator, ensures that whatever the enclosed command outputs is treated as an array, even if only 1 object is output, so that .Length
is guaranteed to be the array's .Length
property.
However, in PSv3+, accessing .Count
instead of .Length
, as in WillPanic's helpful answer, works too - see below.
Without @(...)
, the result may be a single object, because PowerShell automatically unwraps an output collection that contains only 1 object, which yields that one object only, which implies the following:
up to PSv2:
- If that one object happens to have a
.Length
property, its values is returned.
In the case at hand, this is true if the only object returned represents a file (a [System.IO.FileInfo]
instance) (which in turn is true if the directory contains exactly 1 file and no subdirectories, hidden items aside).
A [System.IO.FileInfo]
's instance's .Length
property returns the file's size in bytes. A value of 0
implies an empty file.
(If the only object returned had been a directory (a [System.IO.DirectoryInfo]
instance, .Length
would have returned $null
, because such instances don't have a .Length
property.)
in PSv3+, the workaround is no longer strictly needed, if you use .Count
, because you can treat even a scalar (single object) as if it were an array, with implicit .Length
/ .Count
[1]
properties and the ability to index into (e.g.,
<scalar>[0]
) - these implicit members are known as intrinsic members - but there are caveats:
If Set-StrictMode -Version 2
or higher is in effect, access to .Length
and .Count
properties that don't actually exist on a scalar at hand cause an error.
This behavior is quite unfortunate, however, as these properties should be considered to exist implicitly - if you agree, make your voice heard in GitHub issue #2798.
If the scalar itself has a property such as .Length
or .Count
or supports indexing, that takes precedence - this is why .Count
must be used in this case (as stated, [System.IO.FileInfo]
instances have a .Length
property reporting the file size in bytes); see below for examples.
Using @(...)
avoids such collisions, because the result is always an array.
Member enumeration is the complementary aspect of unification, which allows you to apply a member (property or method) of the items contained in the collection at the collection level, in which case the member is implicitly accessed on every item in the collection, and the resulting values are returned as an array; see below for an example.
To resolve name collisions with member enumeration, a different approach is needed - see this answer.
Examples of PSv3+ unified collection handling
PS> (666).Length
1 # Scalar 666 was implicitly treated as a collection of length 1
PS> (666).Count
1 # Ditto - ** .Count is preferable, because it less often means something else **
# Caveat: A *string* scalar has a native .Length property
PS> ('666').Length; ('666').Count
3 # .Length: The string types's native property: the number of *characters*
1 # .Count: PowerShell's implicit collection handling: 1 *element*
PS> (666)[0]; (666)[-1]
666 # Index [0] always yields the scalar itself.
666 # Ditto for [-1], the *last* element.
# Member enumeration example: get the .Day property value from each
# [datetime] instance stored in an array.
PS> ((Get-Date), (Get-Date).AddDays(-1)).Day
20
19
[1] As PetSerAl points out, up to PSv5.1, an array's .Count
property was an alias property of .Length
, added by PowerShell's ETS (extended type system - see Get-Help about_Types.ps1xml
).
However, this alias property hasn't really been needed since PSv3, when explicitly implemented .NET interface type members were exposed by PowerShell too, providing access to the array type's ICollection.Count
property. v6 will therefore no longer have the alias property, at which point .Count
will directly access ICollection.Count
- see GitHub issue #3222.
Note that PowerShell magic (i.e., an intrinsic member) is still involved when it comes to invoking .Count
on a scalar (non-collection), however.
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…