Arrays Get-ChildItem.Length错误

Arrays Get-ChildItem.Length错误,arrays,powershell,member-enumeration,Arrays,Powershell,Member Enumeration,我正在编写一个递归函数,它遍历一个目录并复制其中的每个文件和文件夹。我在函数中的第一个检查是查看传入的路径是否有子路径。为了找到答案,我使用以下方法: [array]$arrExclude = @("Extras") Function USBCopy { Param ([string]$strPath, [string]$strDestinationPath) try { $pathChildren = Get-ChildItem -Path $strPath

我正在编写一个递归函数,它遍历一个目录并复制其中的每个文件和文件夹。我在函数中的第一个检查是查看传入的路径是否有子路径。为了找到答案,我使用以下方法:

[array]$arrExclude = @("Extras")
Function USBCopy
{
Param ([string]$strPath, [string]$strDestinationPath)
    try
    {
        $pathChildren = Get-ChildItem -Path $strPath
        if($pathChildren.Length -gt 0)
        {
            foreach($child in $pathChildren)
            {
                if($arrExclude -notcontains $child)
                {
                    $strPathChild = "$strPath\$child"
                    $strDestinationPathChild = "$strDestinationPath\$child" 
                    Copy-Item $strPathChild -Destination $strDestinationPathChild
                    USBCopy $strPathChild $strDestinationPathChild  
                }   
            }
        }              
    }
    catch
    {
        Write-Error ("Error running USBCopy: " + $Error[0].Exception.Message)
    }    
}

在大多数情况下,我的函数是有效的,但我的代码会说一个目录是空的,而实际上其中有一个文件。当我调试我的函数时,变量会说文件夹有子文件夹,但变量的长度是0。有人知道如何解决这个问题吗?

尝试
$pathChildren.Count
而不是
$pathChildren.Length
——它将返回数组中的项数。

与以前一样,多次在对这个问题的简短评论中提供了关键指针(他还帮助完善了这个答案):

使用数组子表达式操作符
@(…)
,可以确保即使只输出一个对象,所包含的任何命令输出都被视为数组,因此
.Length
保证是数组的
.Length
属性

但是,在PSv3+中,访问
.Count
而不是
.Length
,如中所示,也起作用-见下文

如果没有
@(…)
,则结果可能是单个对象,因为PowerShell会自动打开仅包含1个对象的输出集合,从而只生成一个对象,这意味着:

  • 小于等于PSv2

    • 如果一个对象恰好具有
      .Length
      属性,则返回其值。
      在本例中,如果返回的唯一对象表示一个文件(一个
      [System.IO.FileInfo]
      实例)(如果目录正好包含一个文件,并且没有子目录,除了隐藏项,则反过来也是如此)。
      [System.IO.FileInfo]
      实例的
      .Length
      属性以字节为单位返回文件大小。值
      0
      表示文件为空。
      (如果返回的唯一对象是目录(一个
      [System.IO.DirectoryInfo]
      实例,
      .Length
      将返回
      $null
      ,因为此类实例没有
      .Length
      属性。)
  • 在PSv3+中,如果您使用
    .Count
    ,则不再严格需要解决方法,因为您甚至可以将标量(单个对象)视为数组,并使用隐式
    .Length
    /
    .Count
    [1] 属性和索引到的能力(例如,
    [0]
    ,但有一些警告

    • 如果
      Set StrictMode-Version 2
      或更高版本有效,访问
      .Length
      .Count
      属性时,手头的标量上实际上不存在的属性会导致错误。
      然而,这种行为是非常不幸的,因为这些属性应该被认为是隐式存在的——如果你同意的话,让别人听到你的声音

    • 如果标量本身有一个属性,如
      .Length
      .Count
      或支持索引,则该属性优先于-这就是为什么在这种情况下必须使用
      .Count
      (如上所述,
      [System.IO.FileInfo]
      实例有一个
      .Length
      属性报告以字节为单位的文件大小);示例见下文

    • 使用
      @(…)
      可以避免此类冲突,因为结果总是一个数组

    • 成员枚举是统一的补充,它允许您应用成员(属性或方法)集合中包含的项的集合级别,在这种情况下,对集合中的每个项隐式访问成员,并将结果值作为数组返回;请参见下面的示例。
      要解决成员枚举的名称冲突,需要一种不同的方法-请参阅我的


PSv3+统一集合处理示例
[1] 正如PetSerAl指出的,在PSv5.1之前,数组的
.Count
属性是由PowerShell的ETS(扩展类型系统-请参阅)添加的
.Length
别名属性。 但是,自从PSv3显式实现以来,实际上并不需要此alias属性。PowerShell也公开了.NET接口类型成员,提供了对数组类型的
ICollection.Count
属性的访问。因此,v6将不再具有alias属性,此时
.Count
将直接访问
I收集.计数
-请参阅。

请注意,在调用“伪”数组(标量)上的
.Count
时,PowerShell magic仍然会涉及。

$pathChildren=@(Get ChildItem-Path$strPath)
OP的可能副本不需要使用PSv2来获得0的可变长度,空文件也会有相同的结果。不管怎样,PetSerAl关于
@(…)
的建议和你在上面扩展的答案肯定是一个更好的实践。(现在)我认为使用
.Count
不仅可以在PSv3+中很好地工作,而且可以说它比
@(…).Length
更加惯用,因为它利用了PSv3+对集合和标量的统一处理(尽管仍然有必要了解潜在的问题,特别是这里调用的
.Count
不是实际的数组)@mklement0感谢您深入了解此操作的方式/原因。我知道避免在数组中使用
.Length
,但我从未花时间理解其背后的原因/方式。您的答案非常有用。
$pathChildren = @(Get-ChildItem -Path $strPath)
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