Powershell 函数变量的范围
我需要递归地计算Powershell 函数变量的范围,powershell,Powershell,我需要递归地计算mp3和flac文件的数量。这是我的密码: function GetStat() { $mp3_count = 0 $flac_count = 0 Set-Variable -Name mp3_count,flac_count -Option AllScope function getFiles($path) { foreach ($item in Get-ChildItem $path)
mp3
和flac
文件的数量。这是我的密码:
function GetStat()
{
$mp3_count = 0
$flac_count = 0
Set-Variable -Name mp3_count,flac_count -Option AllScope
function getFiles($path)
{
foreach ($item in Get-ChildItem $path)
{
if (Test-Path $item.FullName -PathType Container)
{
GetFiles $item.FullName
}
else
{
if ($item.Extension -eq ".mp3")
{
$mp3_count = $mp3_count + 1
}
if ($item.Extension -eq ".flac")
{
$flac_count = $flac_count + 1
}
}
}
}
getFiles "Y:\music (flac)\Alternative"
$mp3_count
$flac_count
}
我的函数写入0,0
,它看起来像$mp3\u count
和flac\u count
变量在每次调用函数getFiles()
时重置
如何修复代码?一般来说,除非绝对需要,否则不要触及全局范围。函数中有一大堆额外的东西,包括一个不必要的嵌套函数。这是做同样事情的更实际的方法:
# Functions should be named Verb-<Whatever>
function Get-MediaStats ($Path)
{
# Everything that was here was extra and unneeded.
foreach ($item in Get-ChildItem $path -Recurse)
{
if ($item.Extension -eq ".mp3")
{
$mp3_count++
}
if ($item.Extension -eq ".flac")
{
$flac_count++
}
}
# This creates an object... The 'return' or 'write-output' is implied.
[PSCustomObject]@{
'MP3Count' = $mp3_count
'FLACCount' = $flac_count
}
}
# Instead of nested functions you can call the function like so...
# Because it's returning a an object the variable $Result will contain the output.
$Results = Get-MediaStats C:\Path\To\Files
$Results
如果您执行了
$Result=返回某些内容这些操作中的任何一个都可以工作,您只需使用Get ChildItem-Recurse
即可跳过所有这些操作。但是如果您想自己实现递归,这里有几个指针
我建议不要在局部范围之外写入变量
让递归函数返回哈希表,然后将每个递归的值添加到本地哈希表:
function Get-FileCount
{
param(
[Parameter(Mandatory=$false)]
[ValidateScript({Test-Path -LiteralPath $_ -PathType Container})]
[string]$Path = (Resolve-Path $PWD),
[Parameter(Mandatory=$false)]
[string[]]$Extensions = @('flac','mp3')
)
# build local table to hold counts per extension
$ExtensionCount = @{}
# add dot to extensions if missing
$Extensions = $Extensions |ForEach-Object {
$_ -replace '^(?=[^\.])','.'
}
# retrieve all items at current $Path
Get-ChildItem -LiteralPath $Path |ForEach-Object {
# recurse if directory
if($_ -is [System.IO.DirectoryInfo]){
# retrieve count from subfolder
$Subcount = Get-FileCount -Path $_.FullName -Extensions $Extensions
foreach($Extension in $Subcount.Keys){
# add results from recursive call for each identified extension to current count
$ExtensionCount[$Extension] += $Subcount[$Extension]
}
}
elseif($_.Extension -in $Extensions) {
# increment count for the found extension in local $Path
$ExtensionCount[$_.Extension]++
}
}
# return the counting table
return $ExtensionCount
}
现在,您可以使用以下命令检索每种类型的计数:
Get-FileCount "Y:\music (flac)\Alternative"
如果要添加新的文件类型,则无需重写任何内容:
Get-FileCount "Y:\music (flac)\Alternative" -Extensions flac,mp3,avi,ogg
我将使用$items=get ChildItem-Recurse-File-Filter“*.mp3”-Path$pathToQuery
递归地获取所有文件。然后用户$items.Count
。您可以使用多个扩展名优化一次扫描,然后使用自定义推理在使用Where Object
进行计数筛选之前进行优化。比如说
$items=Get-ChildItem -Recurse -File -Filter @("*.mp3","*.flac") -Path $pathToQuery
($items|Where-Object {#filter1 reasoning}).Count
($items|Where-Object {#filter2 reasoning}).Count
Mathias R.Jessen已经提供了一个很好的答案,但对于一些简单的问题,您可以使用带有-Recurse
参数的Get ChildItem
,并将其传递到Group Object
以使其变得更简单
Function Get-FileCount{
Param(
[string]$Path,
[string[]]$Extensions = ".MP3",".FLAC"
)
# Sanitize extensions
$Extensions = $Extensions -replace "^(?:.*\.)?([^\.]+)$",'.$1'
#Locate, filter, and group files
Get-ChildItem $Path -Recurse | Where{ $_.Extension -in $extensions } | Group Extension | Select Name,Count
}
然后你可以这样称呼它:
Get-FileCount "Y:\music (flac)\Alternative"
它将输出如下内容:
Name Count
---- -----
.mp3 37
.flac 163
您可以将所有出现的$mp3\u count
替换为$global:mp3\u count
,以便始终在全局范围内读取和写入同一变量。您可以将变量创建为全局变量,但稍后将其设置为未定义(函数中的局部变量)。如上所述,使用范围修饰符。此外,您还可以将所有这些替换为$files=dir-path“Y:\music(flac)\Alternative”-file-recurse$mp3_count=@($files | where{$\扩展名-match'mp3$).count$flac|u count=@($files{$\.extension-match'flac$).count
或$flac|count,$mp3|count=dir“Y:\music(flac)\Alternative”-file-recurse{$\.extension-match'\.flac$\.mp3$”}组扩展名|排序名|选择-展开计数
Name Count
---- -----
.mp3 37
.flac 163