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

时间:2015-02-04 17:55:42

标签: powershell

考虑以下目录树

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

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

    每个BARXXX文件夹
  • 每个BARXXX_Y文件夹
  • 带有" ignore_this"的文本文件在名称中,应该在计数中忽略

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

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似乎是空的。请告诉我我做错了什么。

2 个答案:

答案 0 :(得分:1)

嗯,首先,您正在运行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
    }
}

答案 1 :(得分:1)

我喜欢这种创建对象的方式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)。

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

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

最后,我们可以删除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

干杯人!