优化SharePoint文档库文件计数PowerShell脚本求助
原脚本的问题分析
你的脚本核心问题在于:
- 先拉取所有列表项(包括文件夹),再在本地用
Where过滤文件,10万+量级下会产生大量不必要的数据传输和内存占用,导致速度极慢 - 循环计数的逻辑存在错误:
$counter += $items.Count中的$items是未定义变量,且数组累加的方式效率低下
下面是几种针对大型文档库的高效优化方案:
方案1:使用CAML查询在服务器端过滤文件
直接通过CAML查询让SharePoint服务器只返回文件类型的项,避免本地过滤,大幅减少数据传输量:
#Set Variables $SiteURL= "https://staffordshire.sharepoint.com/sites/CFTTestTeamArea" $ListName= "WIP Temporary" #Connect to PnP Online Connect-PnPOnline -Url $SiteURL -UseWebLogin # 构建CAML查询,仅返回文件类型的项 $camlQuery = @" <View Scope="RecursiveAll"> <Query> <Where> <Eq> <FieldRef Name="FileSystemObjectType"/> <Value Type="Integer">0</Value> <!-- 0代表File,1代表Folder --> </Eq> </Where> </Query> <RowLimit Paged="TRUE">5000</RowLimit> <!-- 最大分页大小,提升批量获取效率 --> </View> "@ # 获取所有文件项并直接计数 $fileCount = (Get-PnPListItem -List $ListName -CamlQuery $camlQuery).Count Write-Host "文件总数:$fileCount" # 导出到CSV [PSCustomObject]@{ 站点URL = $SiteURL 文档库名称 = $ListName 文件数量 = $fileCount } | Export-Csv -Path "./文件计数结果.csv" -NoTypeInformation -Encoding UTF8
优势:服务器端过滤仅返回文件数据,用最大5000条分页(比默认500更快),直接取集合长度计数,无需循环。
方案2:使用Get-PnPFolder递归统计文件
利用Get-PnPFolder的递归功能直接统计文件数量,无需拉取所有列表项:
#Set Variables $SiteURL= "https://staffordshire.sharepoint.com/sites/CFTTestTeamArea" $ListName= "WIP Temporary" #Connect to PnP Online Connect-PnPOnline -Url $SiteURL -UseWebLogin # 获取文档库根文件夹,递归统计所有文件 $rootFolder = Get-PnPFolder -List $ListName -Includes Files, Folders $fileCount = 0 function CountFiles($folder) { $script:fileCount += $folder.Files.Count foreach ($subFolder in $folder.Folders) { CountFiles (Get-PnPFolder -Identity $subFolder.ServerRelativeUrl -Includes Files, Folders) } } CountFiles $rootFolder Write-Host "文件总数:$fileCount" # 导出到CSV [PSCustomObject]@{ 站点URL = $SiteURL 文档库名称 = $ListName 文件数量 = $fileCount } | Export-Csv -Path "./文件计数结果.csv" -NoTypeInformation -Encoding UTF8
优势:仅获取文件夹和文件的计数信息,不返回完整列表项数据,内存占用更低。
方案3:使用REST API直接获取文件计数(最快方案)
通过REST API直接请求统计结果,完全避免拉取任何项数据,速度最快,适合超大型库:
#Set Variables $SiteURL= "https://staffordshire.sharepoint.com/sites/CFTTestTeamArea" $ListName= "WIP Temporary" #Connect to PnP Online Connect-PnPOnline -Url $SiteURL -UseWebLogin # 获取文档库ID $list = Get-PnPList -Identity $ListName $listId = $list.Id.ToString() # 构造REST API请求,获取文件总数 $apiUrl = "$SiteURL/_api/web/lists('$listId')/items`?$filter=FileSystemObjectType eq 0&$select=Id&$top=1&$inlinecount=allpages" $response = Invoke-PnPSPRestMethod -Url $apiUrl -Method Get $fileCount = $response.'odata.count' Write-Host "文件总数:$fileCount" # 导出到CSV [PSCustomObject]@{ 站点URL = $SiteURL 文档库名称 = $ListName 文件数量 = $fileCount } | Export-Csv -Path "./文件计数结果.csv" -NoTypeInformation -Encoding UTF8
优势:仅返回计数数字,数据传输量极小,10万+文件的场景下几乎瞬间完成。
批量处理多个站点/文档库
如果需要处理多个站点和文档库,可以把逻辑封装为函数批量遍历:
function Get-SPFileCount { param( [Parameter(Mandatory=$true)] [string]$SiteURL, [Parameter(Mandatory=$true)] [string]$ListName ) Connect-PnPOnline -Url $SiteURL -UseWebLogin $list = Get-PnPList -Identity $ListName $listId = $list.Id.ToString() $apiUrl = "$SiteURL/_api/web/lists('$listId')/items`?$filter=FileSystemObjectType eq 0&$select=Id&$top=1&$inlinecount=allpages" $response = Invoke-PnPSPRestMethod -Url $apiUrl -Method Get return [PSCustomObject]@{ 站点URL = $SiteURL 文档库名称 = $ListName 文件数量 = $response.'odata.count' } } # 批量处理示例 $libraries = @( @{SiteURL="https://staffordshire.sharepoint.com/sites/CFTTestTeamArea"; ListName="WIP Temporary"}, @{SiteURL="https://staffordshire.sharepoint.com/sites/AnotherSite"; ListName="Documents"} ) $results = foreach ($lib in $libraries) { Get-SPFileCount -SiteURL $lib.SiteURL -ListName $lib.ListName } $results | Export-Csv -Path "./批量文件计数结果.csv" -NoTypeInformation -Encoding UTF8
内容的提问来源于stack exchange,提问作者Dominic Gibson
相关产品推荐
相关产品推荐

