Powershell - 在目录的长文件路径中查找嵌套文件夹的数量
Powershell - Find # of nested folders in long file path of a directory
任何人都可以帮助我解决 powershell 中的代码难题吗?我正在尝试查看多个远程服务器上的特定目录,并在该目录中找到最深的嵌套子文件夹,然后计算父文件夹的数量。下面是伪代码。
- $servers = get-content(服务器列表)和 $path =(远程机器上的目标目录)
- 对于 $servers 中的每个 $s:
- 找到最长的路径
- 计算 \ 的数量(以识别子文件夹的数量)
- 将输出写入文件 $Servername $countOfNestedFolders
抱歉,我只是足够好,有点危险。
解决你的核心问题:
对于给定的 $path
,您可以在其子树中找到 最大目录深度 - 表示为路径分隔符的数量(\
Windows, /
on 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
输出目录$path
的(-Recurse
)的整个子树中的所有子目录(-Directory
);添加 -Force
以包含隐藏的子目录。 - 见 Get-ChildItem
.
Measure-Object -Maximum { ($_.FullName -split '[\/]').Count }
计算路径分隔符的数量([\/]
是一个匹配单个 \
和 /
字符的正则表达式。)每个目录的完整路径 ($_.FullName
) - 使用 脚本块 {...}
作为(隐含的)-Property
参数,其中 $_
表示手头的输入路径 - 并确定最大值 (-Maximum
);给定 Measure-Object
outputs a Microsoft.PowerShell.Commands.GenericMeasureInfo
实例,通过 .Maximum
属性.
访问原始最大值
所有附带任务 - 将此计算应用于多个服务器,将结果写入 server-specific 文件 - 可以使用常用的 cmdlet (Get-Content
, ForEach-Object
, Set-Content
or Out-File
/ >
) 完成。
更快的选择:
上面的命令简洁PowerShell-idiomatic,但是有点慢。
这是一个明显更快的替代方法,它直接使用 LINQ 和 .NET API:
# 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')
)
注意:上面总是包含 隐藏 目录。在 .NET Core / .NET 5+ 中,[System.IO.Directory]::GetDirectories()
现在提供了一个 additional overload,可以更好地控制枚举。
也列出 maximum-depth 目录:
如果您不仅要计算最大深度,还想列出所有具有最大深度的目录(注意可以有多个):
# 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
,您将得到如下内容:
MaxDepth : 6
MaxDepthDirs : {/Users/jdoe/Documents/Ram Dass Audio Collection/The Path of Service, /Users/jdoe/Documents/Ram Dass Audio Collection/Conscious Aging,
/Users/jdoe/Documents/Ram Dass Audio Collection/Cultivating the Heart of Compassion, /Users/jdoe/Documents/Cheatsheets/YAML Ain't
Markup Language_files}
由于您要查找最大计数,因此您似乎需要进行比较。基本上,从大小 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
。所以我刚刚发布了分隔符计数。
它的作用...
- 设置顶级目录从
开始工作
- 获取目录分隔符字符
- 创建该字符的正则表达式转义版本
- 抓取目标目录树中的所有目录
- 根据删除所有内容时剩余内容的字符串长度[按降序]对它们进行排序除了目录分隔符
- 抓住第一个目录
- 显示该目录的
.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
}
任何人都可以帮助我解决 powershell 中的代码难题吗?我正在尝试查看多个远程服务器上的特定目录,并在该目录中找到最深的嵌套子文件夹,然后计算父文件夹的数量。下面是伪代码。
- $servers = get-content(服务器列表)和 $path =(远程机器上的目标目录)
- 对于 $servers 中的每个 $s:
- 找到最长的路径
- 计算 \ 的数量(以识别子文件夹的数量)
- 将输出写入文件 $Servername $countOfNestedFolders
抱歉,我只是足够好,有点危险。
解决你的核心问题:
对于给定的 $path
,您可以在其子树中找到 最大目录深度 - 表示为路径分隔符的数量(\
Windows, /
on 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
输出目录$path
的(-Recurse
)的整个子树中的所有子目录(-Directory
);添加-Force
以包含隐藏的子目录。 - 见Get-ChildItem
.
访问原始最大值Measure-Object -Maximum { ($_.FullName -split '[\/]').Count }
计算路径分隔符的数量([\/]
是一个匹配单个\
和/
字符的正则表达式。)每个目录的完整路径 ($_.FullName
) - 使用 脚本块{...}
作为(隐含的)-Property
参数,其中$_
表示手头的输入路径 - 并确定最大值 (-Maximum
);给定Measure-Object
outputs aMicrosoft.PowerShell.Commands.GenericMeasureInfo
实例,通过.Maximum
属性.
所有附带任务 - 将此计算应用于多个服务器,将结果写入 server-specific 文件 - 可以使用常用的 cmdlet (Get-Content
, ForEach-Object
, Set-Content
or Out-File
/ >
) 完成。
更快的选择:
上面的命令简洁PowerShell-idiomatic,但是有点慢。 这是一个明显更快的替代方法,它直接使用 LINQ 和 .NET API:
# 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')
)
注意:上面总是包含 隐藏 目录。在 .NET Core / .NET 5+ 中,[System.IO.Directory]::GetDirectories()
现在提供了一个 additional overload,可以更好地控制枚举。
也列出 maximum-depth 目录:
如果您不仅要计算最大深度,还想列出所有具有最大深度的目录(注意可以有多个):
# 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
,您将得到如下内容:
MaxDepth : 6
MaxDepthDirs : {/Users/jdoe/Documents/Ram Dass Audio Collection/The Path of Service, /Users/jdoe/Documents/Ram Dass Audio Collection/Conscious Aging,
/Users/jdoe/Documents/Ram Dass Audio Collection/Cultivating the Heart of Compassion, /Users/jdoe/Documents/Cheatsheets/YAML Ain't
Markup Language_files}
由于您要查找最大计数,因此您似乎需要进行比较。基本上,从大小 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
。所以我刚刚发布了分隔符计数。
它的作用...
- 设置顶级目录从 开始工作
- 获取目录分隔符字符
- 创建该字符的正则表达式转义版本
- 抓取目标目录树中的所有目录
- 根据删除所有内容时剩余内容的字符串长度[按降序]对它们进行排序除了目录分隔符
- 抓住第一个目录
- 显示该目录的
.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
}