【问题标题】:How do I include the base folder in the list of sub-folders using get-childitem?如何使用 get-childitem 在子文件夹列表中包含基本文件夹?
【发布时间】:2015-03-19 23:22:34
【问题描述】:

我想在子目录列表中包含基本文件夹。

如果我使用 Get-ChildItem 并搜索文件夹:

$startFolder = "C:\Scripts"
Get-ChildItem $startfolder -recurse |
Where-Object {$_.PSIsContainer -eq $True} | 
Select FullName

我得到一个这样的子文件夹列表:

C:\Scripts\folder1
C:\Scripts\folder2
C:\Scripts\folder2\folderA

我想看看:

C:\Scripts             <-- include the starting folder
C:\Scripts\folder1
C:\Scripts\folder2
C:\Scripts\folder2\folderA

我在technet上看到一个这样的例子:

$startFolder = "C:\Scripts"
$colItems = (Get-ChildItem $startFolder | Measure-Object -property length -sum)
"$startFolder -- " + "{0:N2}" -f ($colItems.sum / 1MB) + " MB"

$colItems = (Get-ChildItem $startFolder -recurse | Where-Object {$_.PSIsContainer -eq $True} | Sort-Object)
foreach ($i in $colItems)
    {
        $subFolderItems = (Get-ChildItem $i.FullName | Measure-Object -property length -sum)
        $i.FullName + " -- " + "{0:N2}" -f ($subFolderItems.sum / 1MB) + " MB"
    }

他们把它分成两部分。处理起始文件夹,然后处理子文件夹。这是唯一的方法还是可以将起始文件夹包含在一个命令中?

这似乎是一件很简单的事情......

【问题讨论】:

标签: powershell powershell-3.0


【解决方案1】:

一种解决方案:

$startFolder = "C:\Scripts"
$(Get-Item $startFolder
Get-ChildItem $startfolder -recurse |
Where-Object {$_.PSIsContainer -eq $True}) | 
Select FullName

为您的 $startFolder 添加一个Get-Item,并将它与您的Get-ChildItem 一起包装在一个sub-expression 中,这样它们就在同一个集合中。

【讨论】:

  • 此解决方案通常是此方案可接受的解决方案。
  • 谢谢。太糟糕了,它不包含那个参数
  • @kevro 对该评论的响应是以 cmdlet 的名称命名的 Get-ChildItem 是获取子项而不是主机。这往往是人们正在寻找的。​​span>
【解决方案2】:

如果您不喜欢这种行为,请更改它。如果你使用这两行,你可以得到一个代理函数的骨架:

$MetaData = New-Object System.Management.Automation.CommandMetaData (Get-Command Get-ChildItem)
[System.Management.Automation.ProxyCommand]::Create($MetaData)

然后你可以在进程块中添加这段代码:

$GetItemParams = @{
    Force = $Force
}
switch ($PSCmdlet.ParameterSetName) {
    Items { $GetItemParams.Path = $Path }
    LiteralItems { $GetItemParams.LiteralPath = $LiteralPath }

    default {
        Write-Error "Unable to call Get-Item on base: Unknown ParameterSetName"
    }
}
Get-Item @GetItemParams

完成此操作后,您的最终代理函数将如下所示:

function Get-ChildItem {
    [CmdletBinding(DefaultParameterSetName='Items', SupportsTransactions=$true, HelpUri='http://go.microsoft.com/fwlink/?LinkID=113308')]
    param(
        [Parameter(ParameterSetName='Items', Position=0, ValueFromPipeline=$true, ValueFromPipelineByPropertyName=$true)]
        [string[]]
        ${Path},

        [Parameter(ParameterSetName='LiteralItems', Mandatory=$true, ValueFromPipelineByPropertyName=$true)]
        [Alias('PSPath')]
        [string[]]
        ${LiteralPath},

        [Parameter(Position=1)]
        [string]
        ${Filter},

        [string[]]
        ${Include},

        [string[]]
        ${Exclude},

        [Alias('s')]
        [switch]
        ${Recurse},

        [switch]
        ${Force},

        [switch]
        ${Name})

    begin
    {
        try {
            $outBuffer = $null
            if ($PSBoundParameters.TryGetValue('OutBuffer', [ref]$outBuffer))
            {
                $PSBoundParameters['OutBuffer'] = 1
            }
            $wrappedCmd = $ExecutionContext.InvokeCommand.GetCommand('Get-ChildItem', [System.Management.Automation.CommandTypes]::Cmdlet)
            $scriptCmd = {& $wrappedCmd @PSBoundParameters }
            $steppablePipeline = $scriptCmd.GetSteppablePipeline($myInvocation.CommandOrigin)
            $steppablePipeline.Begin($PSCmdlet)
        } catch {
            throw
        }
    }

    process
    {
        # Modification starts here
        $GetItemParams = @{
            Force = $Force
        }
        switch ($PSCmdlet.ParameterSetName) {
            Items { $GetItemParams.Path = $Path }
            LiteralItems { $GetItemParams.LiteralPath = $LiteralPath }

            default {
                Write-Error "Unable to call Get-Item on base: Unknown ParameterSetName"
            }
        }
        Get-Item @GetItemParams
        # Modification ends here

        try {
            $steppablePipeline.Process($_)
        } catch {
            throw
        }
    }

    end
    {
        try {
            $steppablePipeline.End()
        } catch {
            throw
        }
    }
    <#

    .ForwardHelpTargetName Get-ChildItem
    .ForwardHelpCategory Cmdlet

    #>

}

当然,如果您不希望每次尝试使用 Get-ChildItem 时都调用您的函数,您可以随意命名该函数。

【讨论】:

    【解决方案3】:

    我喜欢文件系统安全 PowerShell 模块 3.2.3 (NTFSSecurity),它允许长文件夹名称并包含 -Directory 标志,因此我的解决方案如下:

    ((Get-Item2 -Path $startFolder -ErrorAction SilentlyContinue),
     (Get-ChildItem2 -Path $startFolder -Recurse -Directory -ErrorAction SilentlyContinue)).FullName |
         ForEach-Object {
              process-folder $_ ...
         }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2019-08-27
      • 1970-01-01
      • 1970-01-01
      • 2015-10-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多