You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PowerShell递归统计文件夹文件数与Windows显示不符求助

PowerShell文件统计与资源管理器计数不一致的解决建议

问题描述

我使用以下PowerShell脚本将指定UNC路径映射为驱动器,递归统计目标文件夹的文件数量,当文件数超过设定阈值时发送告警邮件。但脚本统计的文件数始终与Windows资源管理器显示的文件数存在差异,恳请提供解决建议。

脚本内容

<#
------------------------C-O-U-N-T-&-R-E-P-O-R-T----------------------- 
                                                                      #>

# 变量定义
$DriveLetter = "N" # 网络驱动器盘符
$NetworkPath = "\\10.1.10.10\ebys_tmp"
$Username = "svc_userInfo"   
$Password = ConvertTo-SecureString "passw0rD!!" -AsPlainText -Force

$LogServer = "contoso-eposta-01"   # 远程服务器名称
$eventLogName = "Application"     # 事件日志名称
$eventLogSource = "EBYS FileCount"     # 事件日志来源

$LogServerUsername = "contoso\svc_userinfo"  # 远程服务器用户名
$LogServerPassword = ConvertTo-SecureString "Passw0rD!!" -AsPlainText -Force  # 远程服务器密码
$LogServerCredential = New-Object System.Management.Automation.PSCredential($remoteUsername, $remotePassword)

try
{
    # 定义网络驱动器访问凭据
    $Credential = New-Object System.Management.Automation.PSCredential ($Username, $Password)

    # 检查驱动器盘符是否已存在
    $existingDrive = Get-PSDrive -Name $DriveLetter -ErrorAction SilentlyContinue

    # 如果盘符已存在
    if ($existingDrive -ne $null) {
        Write-Host "驱动器 $DriveLetter 已存在,直接进入统计步骤。"
    } else {
        # 将UNC路径映射为网络驱动器
        New-PSDrive -Name $DriveLetter -PSProvider FileSystem -Root $NetworkPath -Credential $Credential -Persist
        Write-Host "驱动器 $DriveLetter 映射成功。"
    }

    # 递归统计文件数量
    $fileCount = (Get-ChildItem -Recurse -File -Exclude 'RtBackup').Count
    $fileLimit = 30000

    <# 远程服务器创建事件日志记录
$remoteServer = "contoso-eposta-01"   # 远程服务器名称
$eventLogName = "Application"     # 事件日志名称
$eventLogSource = "EBYS FileCount"     # 事件日志来源

$remoteUsername = "contoso.org\svc_ebystmpinfo"  # 远程服务器用户名
$remotePassword = ConvertTo-SecureString "Passw0rD!!" -AsPlainText -Force  # 远程服务器密码
$remoteCredential = New-Object System.Management.Automation.PSCredential($remoteUsername, $remotePassword)
#>

    if ($fileCount -ge $fileLimit)  {
        # SMTP服务器与邮件设置
        $smtpUsername = "svc_userinfo"
        $smtpPassword = ConvertTo-SecureString "Passw0rD!!" -AsPlainText -Force
        $smtpCredential = New-Object System.Management.Automation.PSCredential ($smtpUsername, $smtpPassword)

        $emailFrom = "testuser@contoso.org"
        $emailTo = "testuser2@contoso.org"
        $emailSubject = "EBYS TMP FOLDER MONITOR"
        $emailBody = @"
<!DOCTYPE html>
<html>
<head>
    <style>
        table {
            width:450px;
            border: 1px solid #b3adad;
            border-collapse: collapse;
            padding: 5px;
        }
        table th {
            border: 1px solid #b3adad;
            padding: 5px;
            background: #ffbb00;
            color: #313030;
        }
        table td {
            border: 1px solid #b3adad;
            text-align: center;
            padding: 5px;
            background: #ffffff;
            color: #313030;
        }
    </style>
</head>
<body>
    <table>
        <thead>
            <tr>
                <th colspan="2">CONTOSO ORG - 系统服务</th>
            </tr>
        </thead>
        <tbody>
            <tr>
                <td>允许的最大文件数:</td>
                <td>$fileLimit</td>
            </tr>
            <tr>
                <td>当前文件数:</td>
                <td>$fileCount</td>
            </tr>
            <tr>
                <td colspan="2">$NetworkPath 文件夹中的文件数已超过设定阈值 $fileLimit,当前文件数为: $fileCount</td>
            </tr>
        </tbody>
    </table>
</body>
</html>
"@

        # 发送邮件
        Send-MailMessage -To $emailTo -From $emailFrom -Subject $emailSubject -Credential $smtpCredential -SmtpServer "ibb-eposta-01.ibb.net" -Body $emailBody -BodyAsHtml -Encoding UTF8
    }
}
catch
{
    Write-Host "发生错误。"
    <# 远程服务器创建事件日志记录
$remoteServer = "contoso-eposta-01"   # 远程服务器名称
$eventLogName = "Application"     # 事件日志名称
$eventLogSource = "EBYS FileCount"     # 事件日志来源

$remoteUsername = "contoso.org\svc_userinfo"  # 远程服务器用户名
$remotePassword = ConvertTo-SecureString "passwOrDHere!!" -AsPlainText -Force  # 远程服务器密码
$remoteCredential = New-Object System.Management.Automation.PSCredential($remoteUsername, $remotePassword)
#>
}
finally
{
    Write-EventLog 
}

解决建议

  • 排除规则错误:脚本中-Exclude 'RtBackup'仅会排除名为RtBackup的文件,而非文件夹。如果需要排除RtBackup文件夹内的所有文件,应改用路径过滤:

    $fileCount = (Get-ChildItem -Recurse -File | Where-Object { $_.FullName -notmatch '\\RtBackup\\' }).Count
    
  • 未包含隐藏/系统文件:Windows资源管理器默认可能显示隐藏和系统文件,但Get-ChildItem默认不会统计这些文件。添加-Force参数即可获取全部文件:

    $fileCount = (Get-ChildItem -Recurse -File -Force | Where-Object { $_.FullName -notmatch '\\RtBackup\\' }).Count
    
  • 权限差异:脚本使用svc_userInfo账号访问,可能没有部分子文件夹的权限,导致统计遗漏;而资源管理器使用当前登录用户权限,可访问更多内容。可添加错误捕获查看无法访问的路径:

    Get-ChildItem -Recurse -File -Force -ErrorAction SilentlyContinue -ErrorVariable accessErrors
    if ($accessErrors) {
        Write-Host "无法访问的路径:"
        $accessErrors | ForEach-Object { Write-Host $_.TargetObject }
    }
    
  • 网络映射延迟:刚完成驱动器映射就立即统计,可能因网络延迟导致部分文件未加载。可添加短暂延迟:

    Start-Sleep -Seconds 5
    
  • 资源管理器缓存:资源管理器可能使用缓存的计数,并非实时统计。按F5刷新资源管理器后再对比数值。

  • 直接访问UNC路径:映射驱动器可能因权限或缓存导致统计偏差,直接访问UNC路径更准确,无需映射驱动器:

    $fileCount = (Get-ChildItem -Path $NetworkPath -Recurse -File -Force -Credential $Credential | Where-Object { $_.FullName -notmatch '\\RtBackup\\' }).Count
    

内容的提问来源于stack exchange,提问作者deadp1XL

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.07 02:27:05