Powershell使用文件夹列表操纵阵列以仅显示最后一个文件夹

Powershell使用文件夹列表操纵阵列以仅显示最后一个文件夹,powershell,Powershell,我必须为我的工作环境(广告中有500多个用户)设置一个基于Windows的文件共享服务器,我想用powershell实现自动化。我想根据广告层次结构中的OU创建文件夹,然后将权限分配给实际在这些部门工作的人员组。每个ou=部门,有时在部门下有团队,甚至更小的组织单位。因此,我将使用混合文件夹结构,如: 根目录/第1层/第2层/第3层/他们的文件和文件夹 根目录/Tier\u 1/Tier\u 2/其\u文件和\u文件夹 根目录/层1/他们的文件和文件夹 当然,每一层都可以有不同的名称,我希望你能

我必须为我的工作环境(广告中有500多个用户)设置一个基于Windows的文件共享服务器,我想用powershell实现自动化。我想根据广告层次结构中的OU创建文件夹,然后将权限分配给实际在这些部门工作的人员组。每个ou=部门,有时在部门下有团队,甚至更小的组织单位。因此,我将使用混合文件夹结构,如:

根目录/第1层/第2层/第3层/他们的文件和文件夹

根目录/Tier\u 1/Tier\u 2/其\u文件和\u文件夹

根目录/层1/他们的文件和文件夹

当然,每一层都可以有不同的名称,我希望你能理解

我的问题是,在人们开始使用我的服务器并开始创建他们自己的文件夹后,我不知道如何获取仅由基于广告树的脚本创建的最后文件夹列表(因为我可以基于它们授予权限),这将使我的当前方法无法工作。 我目前的方法是:

Get-childitem "path_to_root_shared_directory" -r -directory | Where-Object {$_.GetDirectories().Count -eq 0}
我想,既然我有一个基于AD创建的文件夹列表(在一个变量数组中),也许我可以通过某种方式操纵该数组,只获得最后的文件夹。我的意思是比较文件夹路径以创建并只保留到没有更多子文件夹(叶文件夹)的文件夹的路径。因此,如果我有如下文件夹结构:

根目录

基层主任/部门主任

总经理/部门/团队

基层主任/部门A/团队B

基层主任/部门主任

只离开:

总经理/部门/团队

基层主任/部门A/团队B

基层主任/部门主任

我希望你们能理解我想要实现的目标;)

以下是一种方法:

Get-ChildItem "C:\RootDirectory" -Directory -Recurse |
    ForEach-Object {
        if((Get-ChildItem $_.FullName -Directory).Count) {
            $_.FullName
        }
    } | Sort-Object

您将在下面找到第三个解决方案的一个改编,它从开始到完成我需要在列表中逐个查看它们的请求,这样我就可以进行另一个foreach循环并基于它们添加权限

产出:

PS C:\> $dirScan = @(Get-ChildItem C:\test -Recurse -Directory | Select-Object -ExpandProperty FullName | Sort-Object)
PS C:\> $dirScan
C:\test\a-level1
C:\test\a-level1\a-level2
C:\test\a-level1\b-level2
C:\test\a-level1\b-level2\a-level3
C:\test\a-level1\b-level2\b-level3
C:\test\a-level1\b-level2\c-level3
C:\test\a-level1\b-level2\c-level3\a-level4
C:\test\b-level1
C:\test\c-level1
C:\test\c-level1\a-level2
C:\test\c-level1\b-level2
C:\test\c-level1\b-level2\a-level3
PS C:\> Get-MostDepthDirectory $dirScan
C:\test\a-level1\a-level2
C:\test\a-level1\b-level2\a-level3
C:\test\a-level1\b-level2\b-level3
C:\test\a-level1\b-level2\c-level3\a-level4
C:\test\b-level1
C:\test\c-level1\a-level2
C:\test\c-level1\b-level2\a-level3
PS C:\> Get-MostDepthDirectory C:\test
C:\test\a-level1\a-level2
C:\test\a-level1\b-level2\a-level3
C:\test\a-level1\b-level2\b-level3
C:\test\a-level1\b-level2\c-level3\a-level4
C:\test\b-level1
C:\test\c-level1\a-level2
C:\test\c-level1\b-level2\a-level3
PS C:\>
编辑:我添加了一点解释

代码段创建了一个
Get-MostDepthDirectory
CmdLet,可以使用要筛选的目录数组或要扫描的目录调用该CmdLet

如果使用要扫描的目录调用(
ParameterSetName=“DirectoryScan”
),它将构建一个
$subDirectories
变量,其中包含所有子目录的绝对路径,否则(
ParameterSetName=“DirectoryScan”
)它将直接从参数获取目录列表

它启动一个
System.Collections.ArrayList
对象,它是.NET framework中的一个集合,在这里更合适,因为它有
Add
Remove
方法,允许在不需要知道索引的情况下管理数组内容(否则代码会更复杂)。对象将存储过滤后的列表

然后:

  • 它在子目录列表(
    foreach($d)中循环
    $子目录)

  • 它从目录中提取父目录(
    $t=Split Path$d-parent

  • 如果列表不包含父目录(
    If($deepestDirectories-NotContains$t)
    ),则会添加当前目录(
    $deepestDirectories.Add($d)| Out Null

  • 否则,它将删除父目录(
    $deepestDirectories.Remove($t)| Out Null
    )并添加目录(
    $deepestDirectories.add($d)| Out Null

  • 循环完成后,
    ArrayList
    将被排序并转换为字符串数组,然后返回

    Out Null
    用于阻止
    ArrayList
    对象的
    Add
    Remove
    方法的输出,以将它们的内存状态返回到管道中,否则PowerShell可能会将它们与经过筛选的目录列表一起返回


    希望解释更清楚一点。

    您应该看看这篇文章:我认为这可能很好,但如何使用第三种方法从数组中获取正常的文件夹列表?我需要在一个1乘1的列表中看到它们,这样我就可以进行另一个foreach循环,并根据它们添加权限。谢谢,它可以像我所希望的那样工作(我认为:P)。虽然这对我来说有点复杂。我已经在代码片段上添加了解释。希望有帮助:)很好的解释。如果有人愿意解释的话,我真的很想知道我的代码段出了什么问题?这个解决方案是递归扫描每个目录,每次都计算子目录。它可以工作,但是它消耗了太多的(I/O)资源,随着子目录数量的增加,最终可能会导致整个执行时间非常缓慢;此外,我使用了
    Foreach对象
    而不是
    Foreach($collection中的项目)
    。。。我现在明白了:)。谢谢
    PS C:\> $dirScan = @(Get-ChildItem C:\test -Recurse -Directory | Select-Object -ExpandProperty FullName | Sort-Object)
    PS C:\> $dirScan
    C:\test\a-level1
    C:\test\a-level1\a-level2
    C:\test\a-level1\b-level2
    C:\test\a-level1\b-level2\a-level3
    C:\test\a-level1\b-level2\b-level3
    C:\test\a-level1\b-level2\c-level3
    C:\test\a-level1\b-level2\c-level3\a-level4
    C:\test\b-level1
    C:\test\c-level1
    C:\test\c-level1\a-level2
    C:\test\c-level1\b-level2
    C:\test\c-level1\b-level2\a-level3
    PS C:\> Get-MostDepthDirectory $dirScan
    C:\test\a-level1\a-level2
    C:\test\a-level1\b-level2\a-level3
    C:\test\a-level1\b-level2\b-level3
    C:\test\a-level1\b-level2\c-level3\a-level4
    C:\test\b-level1
    C:\test\c-level1\a-level2
    C:\test\c-level1\b-level2\a-level3
    PS C:\> Get-MostDepthDirectory C:\test
    C:\test\a-level1\a-level2
    C:\test\a-level1\b-level2\a-level3
    C:\test\a-level1\b-level2\b-level3
    C:\test\a-level1\b-level2\c-level3\a-level4
    C:\test\b-level1
    C:\test\c-level1\a-level2
    C:\test\c-level1\b-level2\a-level3
    PS C:\>