问题描述
有人可以通过Powershell中的代码难题帮助我吗?我试图查看多个远程服务器上的特定目录,并在该目录中找到最深的嵌套子文件夹,然后计算父文件夹的数量。下面的伪代码。
- $ servers =获取内容(服务器列表),而$ path =(远程计算机上的targetdir)
- 对于$ servers中的每个$ s:
- 找到最长的路径
- 计算\的数量(以标识子文件夹的数量)
- 将输出写入文件$ Servername $ countOfnestedFolders
对不起,我刚好够时髦,有点危险。
解决方法
要解决您的核心问题:
对于给定的$path
,您可以在其子树中找到最大目录深度-表示为路径分隔符的数量(在Windows中为\
,在{{1} }(在Unix上)),并在/
内嵌套最深的子目录的 full 路径中加上一个-如下:
$path
注意:如果要了解相对于# Outputs the number of path components of the most deeply nested folder in $path.
(Get-ChildItem $path -Recurse -Directory |
Measure-Object -Maximum { ($_.FullName -split '[\\/]').Count }
).Maximum
的相对深度,请将$path
添加到-Name
调用中并替换Get-ChildItem
在脚本块($_.FullName
)中将$_
传递给{ ... }
。结果Measure-Object
意味着0
根本没有子目录,$path
意味着只有直接子目录,1
意味着直接子目录具有(仅)子目录自己...
-
2
输出目录Get-ChildItem -Recurse -Directory $path
的(-Directory
)整个子树中的所有子目录(-Recurse
);添加$path
以包含隐藏的子目录。 -参见Get-ChildItem
。 -
-Force
计算每个目录的完整路径中路径分隔符的数量(Measure-Object -Maximum { ($_.FullName -split '[\\/]').Count }
是一个与单个[\\/]
和\
字符都匹配的正则表达式)。 (/
)-使用 script块$_.FullName
作为(隐含的){...}
自变量,其中-Property
代表当前的输入路径-并确定最大值($_
);假设Measure-Object
输出一个Microsoft.PowerShell.Commands.GenericMeasureInfo
实例,则可以通过-Maximum
属性访问原始最大值。
所有附带任务-将此计算应用于多个服务器,将结果写入特定于服务器的文件-可以使用常规cmdlet(Get-Content
,ForEach-Object
,Set-Content
或{ {3}} / .Maximum
)。
一个更快的选择:
上面的命令简洁明了,PowerShell惯用,但是有点慢。 这是直接使用LINQ和.NET API的一种明显更快的替代方法:
>
注意:上面的内容同样也包含 hidden 目录。在.NET Core / .NET 5+中,# Note: Makes sure that $path is a *full* path,because .NET's current
# directory usually differs from PowerShell's.
1 + [Linq.Enumerable]::Max(
([System.IO.Directory]::GetDirectories(
$path,'*','AllDirectories'
) -replace '[^\\/]').ForEach('Length')
)
现在提供了Out-File
,它提供了对枚举的更多控制。
也列出最大深度目录:
如果您不仅要计算最大深度,还希望列出所有具有最大深度的目录(请注意,可以有多个目录):
[System.IO.Directory]::GetDirectories()
输出是具有# Sample input path.
# Note: Makes sure that $path is a *full* path,because .NET's current
# directory usually differs from PowerShell's.
$path = $PWD
# Extract all directories with the max. depth using Group-Object:
# Group by the calculated depth and extract the last group,which relies on
# Group-Object outputting the results sorted by grouping criteria.
$maxDepthGroup =
[System.IO.Directory]::GetDirectories($path,'AllDirectories') |
Group-Object { ($_ -split '[\\/]').Count } |
Select-Object -Last 1
# Construct the output object.
[pscustomobject] @{
MaxDepth = $maxDepthGroup.Values[0] # The grouping criterion,i.e. the depth.
MaxDepthDirs = $maxDepthGroup.Group # The paths comprising the group.
}
和.MaxDepth
(具有最大深度的那些方向的完整路径的数组)属性的自定义对象。如果将其通过管道传输到.MaxDepthDirs
,则会得到类似以下内容的信息:
Format-List
,
由于您要查找最大数量,因此听起来好像您想进行比较。基本上,从0开始-如果要查看的文件夹大于该大小,则它将变为最大。对所有文件夹执行此操作,直到剩下最大的文件夹为止。请注意,如果有任何关系,此方法将不起作用,但听起来并不像您要找的那样。我应该添加这是查看单台计算机的主要代码。您可以将foreach {$server in $servers}
包裹在多个服务器上。
$folders = Get-ChildItem -Path "C:\Directory" -Directory -Recurse
$n = 0
$biggest = ""
foreach ($folder in $folders)
{
$splitout = $folder.FullName.split("\")
if ($splitout.count -gt $n)
{
$n = $splitout.count
$biggest = $folder
}
}
Write-host "Count $n - $biggest"
,
这是“计算路径部分”解决方案的略微变体。 [ grin ]会计算定界符。如果您的路径是UNC路径还是本地路径,这仍将为您提供最深层的嵌套目录。
但是,它不适用于UNC [\\SysName\ShareName
]和本地[c:\
]混合路径。
而且,它不会从结果中删除起始目录。
也,我不确定您想要如何count number of parent folders
。所以我刚刚发布了定界符计数。
它做什么...
- 设置工作的最高目录
- 获取目录定界符char
- 创建该字符的正则表达式转义版本
- 抓住目标目录树中的所有目录
- 将删除所有内容的字符串长度按[降序]排序[em> dir分隔符
- 抢夺这些第一名
- 显示该目录的
.FullName
- 在上面的字符串中显示目录定界符的数量
代码...
$TargetTopDir = $env:APPDATA
$DirDelim = [System.IO.Path]::DirectorySeparatorChar
$RegexDD = [regex]::Escape($DirDelim)
$DirList = Get-ChildItem -LiteralPath $TargetTopDir -Directory -Recurse
$DeepestNestedDir = ($DirList |
Sort-Object {$_.FullName -replace "[^$RegexDD]"} -Descending)[0]
$DeepestNestedDir.FullName
'DirDelimCount = {0}' -f ($DeepestNestedDir.FullName -replace "[^$RegexDD]").Length
输出...
C:\Users\MyUserName\AppData\Roaming\Thunderbird\Profiles\shkjhmpc.default\extensions\{e2fda1a4-762b-4020-b5ad-a41df1933103}\chrome\calendar-gd\locale\gd\calendar\dialogs
DirDelimCount = 15
,
这完成了;再次感谢您的所有帮助!
$servers = gc C:\serverlist.txt
ForEach ($server in $servers){
$folder = "\\$server\x$\share"
$TargetTopDir = $folder
$DirDelim = [System.IO.Path]::DirectorySeparatorChar
$RegexDD = [regex]::Escape($DirDelim)
$DirList = Get-ChildItem -LiteralPath $TargetTopDir -Directory -Recurse -ErrorAction
SilentlyContinue
$DeepestNestedDir = ($DirList | Sort-Object {$_.FullName -replace "[^$RegexDD]"} -
Descending)[0]
$DepthCount = '{0}' -f ($DeepestNestedDir.FullName -replace "[^$RegexDD]").Length
$arrayItems = @{
"Depth Count" = $DepthCount - 3
"Path Name" = $DeepestNestedDir.FullName
"Server Name" = $server
}
$output= @()
$output += New-Object -TypeName PSObject -Property $arrayItems
$output | Export-CSV C:\Output.csv -NoTypeInformation -Append
}