计算每个子文件夹中的文件数,忽略具有特定名称的文件

Count number of files in each subfolder, ignoring files with certain name

考虑以下目录树

ROOT
    BAR001
        foo_1.txt
        foo_2.txt
        foo_ignore_this_1.txt
    BAR001_a
        foo_3.txt
        foo_4.txt
        foo_ignore_this_2.txt
        foo_ignore_this_3.txt
    BAR001_b
        foo_5.txt
        foo_ignore_this_4.txt
    BAR002
        baz_1.txt
        baz_ignore_this_1.txt
    BAR002_a
        baz_2.txt
        baz_ignore_this_2.txt
    BAR002_b
        baz_3.txt
        baz_4.txt
        baz_5.txt
        baz_ignore_this_3.txt
    BAR002_c
        baz_ignore_this_4.txt
    BAR003
        lor_1.txt

结构总是这样,所以没有更深的子文件夹。我正在编写一个脚本来计算文件的数量:

对于上面的示例,这将导致:

Folder      Filecount
---------------------
BAR001      2
BAR001_a    2
BAR001_b    1

BAR002      1
BAR002_a    1
BAR002_b    3
BAR002_c    0

BAR003      1

我现在有:

Function Filecount {
    param(
        [string]$dir
    )
    $childs = Get-ChildItem $dir | where {$_.Attributes -eq 'Directory'}

    Foreach ($childs in $child) {
        Write-Host (Get-ChildItem $dir | Measure-Object).Count;
    }
}


Filecount -dir "C:\ROOT"

(尚未准备好但正在构建)但是,这不起作用。 $child 似乎是空的。请告诉我哪里做错了。

好吧,首先,您是 运行 ForEach ($childs in $child),这种语法是倒退的,所以这会给您带来一些问题!如果你交换它,那么你就是 运行:

ForEach ($child in $childs)

您将得到以下输出:

>2
>2
>1
>1
>1
>3
>0

好的,我带着完整的答案回来了。首先,我没有使用 Write-Out,而是使用 PowerShell 自定义对象让 PowerShell 为我完成繁重的工作。我将 FolderName 设置为 $child.BaseName,然后 运行 $Child.FullName 上的 GCI 以获取文件计数。我已经添加了一个名为 $ignoreme 的额外参数,对于您要忽略的值,它应该有一个星号值。

这里是完整的答案。请记住,我的文件结构与您的略有不同,因此底部的文件数也不同。

Function Filecount {
param(
    [string]$dir="C:\TEMP\Example",
    [string]$ignoreme = "*_*"
)
$childs = Get-ChildItem $dir | where {$_.Attributes -eq 'Directory'}

Foreach ($child in $childs) {
        [pscustomobject]@{FolderName=$child.Name;ItemCount=(Get-ChildItem $child.FullName | ? Name -notlike $ignoreme | Measure-Object).Count}

    }
}


>Filecount | ft -AutoSize

>FolderName ItemCount
>---------- ---------
>BAR001             2
>BAR001_A           1
>BAR001_b           2
>BAR001_C           0
>BAR002             0
>BAR003             0

如果您使用的是 PowerShell v 2.0,请改用此方法。

Function Filecount {
param(
    [string]$dir="C:\TEMP\Example",
    [string]$ignoreme = "*_*"
)
$childs = Get-ChildItem $dir | where {$_.Attributes -eq 'Directory'}

Foreach ($child in $childs) {
    $ObjectProperties = @{
        FolderName=$child.Name
        ItemCount=(Get-ChildItem $child.FullName | ? Name -notlike $ignoreme | Measure-Object).Count}
    New-Object PSObject -Property $ObjectProperties
    }
}

我喜欢这种创建对象的方式 1RedOne,以前没见过,谢谢。

我们可以通过几种方式提高代码的性能。通过使用 Filter Left 原则,即通过执行更少的循环并删除不必要的步骤,任何 cmdlet 的提供程序本质上比 运行 通过 PowerShell 更有效:

    Function Filecount
{
    param
    (
        [string]$dir = ".",
        [parameter(mandatory=$true)]
        [string]$ignoreme
    )

    Get-ChildItem -Recurse -Directory -Path $dir | ForEach-Object `
    {
        [pscustomobject]@{FolderName=$_.Name;ItemCount=(Get-ChildItem -Recurse -Exclude "*$ignoreme*" -Path $_.FullName).count}
    }
}

所以,首先我们可以在顶级目录中使用Get-Childitem的-Directory开关(我知道v3.0及以上版本有这个功能,不知道v2.0)。

然后我们可以将它的输出直接传递到下一个循环,而不用先存储它。

然后我们可以用供应商 -Exclude 替换另一个 Where-Object

最后,我们可以删除 Measure-Object 作为数组的简单计数:

Filecount "ROOT" "ignore_this" | ft -a

FolderName ItemCount
---------- ---------
BAR001             2
BAR001_a           2
BAR001_b           1
BAR002             1
BAR002_a           1
BAR002_b           3
BAR002_c           0
BAR003             1

大家好!