如何使用get-childitem将基本文件夹包含在子文件夹列表中?

时间:2015-03-19 23:22:34

标签: powershell powershell-v3.0

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

如果我使用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"
    }

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

看起来这么简单......

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一起包装在同一个集合中。

答案 1 :(得分:0)

如果您不喜欢这种行为,请进行更改。如果使用这两行,则可以获取代理函数的框架:

$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时调用您的函数,您可以将该函数命名为您想要的任何内容。

答案 2 :(得分:0)

我喜欢文件系统安全性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 $_ ...
     }