我必须为我的工作环境设置一个基于Windows的文件共享服务器(AD中有500多个用户),我想用PowerShell自动化。我想在AD层次结构中基于OU创建文件夹,之后为实际在这些部门中工作的人员分配权限。每个ou =部门,有时在部门之下,有团队,甚至更小的组织单位。所以我将混合文件夹结构,如:
ROOT_DIRECTORY / Tier_1 / Tier_2 / Tier_3 / their_files_and_folders
ROOT_DIRECTORY / Tier_1 / Tier_2 / their_files_and_folders
ROOT_DIRECTORY / Tier_1 / their_files_and_folders
每一层当然可以有不同的名称,我希望你能得到这个想法。
我的问题是我无法弄清楚如何获取仅由我的脚本基于AD树创建的最后文件夹列表(因为我可以基于它们授予权限)之后人们将开始使用我的服务器并开始创建自己的文件夹将使我当前的方法不起作用。 我目前的方法是:
Get-childitem "path_to_root_shared_directory" -r -directory | Where-Object {$_.GetDirectories().Count -eq 0}
我认为,因为我有一个基于AD(在一个变量 - 数组中)创建的文件夹列表,也许我可以操纵该数组只获取最后一个文件夹。我的意思是以某种方式比较文件夹路径来创建和只留下没有更多子文件夹(叶文件夹)的文件夹的路径。所以,如果我有文件夹结构,如:
ROOT_DIR
ROOT_DIR / Department_A
ROOT_DIR / Department_A / Team_A
ROOT_DIR / Department_A / Team_B
ROOT_DIR / Department_B
仅离开:
ROOT_DIR / Department_A / Team_A
ROOT_DIR / Department_A / Team_B
ROOT_DIR / Department_B
我希望你们能理解我想要达到的目标;)。
答案 0 :(得分:2)
您将在下面找到从http://stuart-moore.com/finding-bottom-folders-file-tree-using-powershell/到第三个解决方案的改编,以满足请求我需要在列表1中逐一查看它们,然后我可以创建另一个foreach循环并添加基于权限的在他们身上。
Function Get-MostDepthDirectory {
[CmdletBinding(DefaultParametersetName="DirectoryScan")]
param (
[Parameter(Position=0,Mandatory=$true,ParameterSetName="DirectoryScan")]
[String]$rootDirectory,
[Parameter(Position=0,Mandatory=$true,ParameterSetName="DirectoryList")]
[String[]]$subDirectories
)
if ($PsCmdlet.ParameterSetName -eq "DirectoryScan") {
$subDirectories = Get-ChildItem -Recurse $rootDirectory -Directory | Select-Object -ExpandProperty FullName
}
$deepestDirectories = New-Object System.Collections.ArrayList
foreach ($d in $subDirectories){
$t = Split-Path $d -Parent
if ($deepestDirectories -NotContains $t){
$deepestDirectories.Add($d) | Out-Null
} else {
$deepestDirectories.Remove($t) | Out-Null
$deepestDirectories.Add($d) | Out-Null
}
}
return [string[]]@($deepestDirectories| Sort-Object)
}
输出:
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,可以使用要过滤的目录数组或要扫描的目录来调用。
如果使用要扫描的目录(ParameterSetName="DirectoryScan"
)调用,它会构建一个$subDirectories
变量,其中包含所有子目录的绝对路径,否则(ParameterSetName="DirectoryList"
)它将获取目录列表直接来自参数。
它启动一个System.Collections.ArrayList
对象,这是一个来自.NET框架的集合,这里更合适,因为它有Add
和Remove
方法,允许不需要的数组的管理内容知道索引(否则代码会更复杂)。该对象将存储已过滤的列表。
然后:
它在子目录列表(foreach ($d in
$subDirectories)
)上循环
它从目录($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
用于防止Add
对象的Remove
和ArrayList
方法的输出将其内存状态返回到管道,否则PowerShell可能会返回它们以及过滤的目录列表。
希望通过解释更清楚一点。
答案 1 :(得分:1)
这是一种方法:
#include <stdio.h>
int menu(void);
void choice1(void);
void choice2(void);
void choice3(void);
int main(void) {
int ch;
for (;;) {
switch (ch = menu()) {
case '1': choice1(); continue;
case '2': choice2(); continue;
case '3': choice3(); continue;
case '4':
case EOF: break;
default: printf("Invalid character %c\n", ch); continue;
}
break;
}
return 0;
}
int menu(void) {
char choice;
printf("\nMenu:\n\n");
printf("1) Choice 1.\n");
printf("2) Choice 2.\n");
printf("3) Choice 3.\n");
printf("Choose any of the above, or enter 4 to quit.\n\n");
if (scanf(" %c", &choice) == 1)
return choice;
else
return EOF;
}
void choice1(void) {
printf("\nChoice 1\n");
}
void choice2(void) {
printf("\nChoice 2\n");
}
void choice3(void) {
printf("\nChoice 3\n");
}