首页 > 解决方案 > 从 CSV 文件中添加对带有子文件夹的文件的 NTFS 访问权限

问题描述

我尝试将 NTFS 访问添加到快捷方式。我有一个 csv 文件,其中包含:

Name,AD
Steps Recorder,Group_312312
Snipping Tool,Group_545345
$FolderPath = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\"
$file = "C:\Users\adm\Desktop\Group.csv"
$groups = Get-Content $file | ConvertFrom-Csv
 foreach ($group in $groups){ 
    Add-NTFSAccess -Path (Join-Path -Path $FolderPath -ChildPath ($group.Name+".lnk")) `
                   -Account $group.AD `
                   -AccessRights ReadAndExecute `
    }

我在 $FolderPath 中有很多带有 *.lnk 文件的子文件夹。但是通过这种方式,脚本只能在 $FolderPath 中找到,而没有子文件夹。如何更改脚本以查找所有 *.lnk 文件包括子文件夹?

For example:
C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories\My_programs\OneDrive.lnk

标签: powershellcsv

解决方案


为此,我认为您需要一种不同的方法,在其中递归地获取 *.lnk 文件的集合并过滤以仅获取具有BaseName可在 CSV 中找到的属性的那些文件。

接下来,Group-Object根据它们的 BaseName 对这些 FileInfo 对象进行分组(创建子集合)。

根据文档, cmdletPath上的参数Add-NTFSAccess可以采用路径数组(全名属性),这些可以通过管道传递给它,因此我们可以一次发送每个子集合:

$FolderPath = "C:\ProgramData\Microsoft\Windows\Start Menu\Programs\Accessories"
$file       = "C:\Users\adm\Desktop\Group.csv"
$groups     = Import-Csv -Path $file

# get a list of *.lnk FileIfo objects where the file's BaseName can be found in the
# CSV column 'Name'. Group these files on their BaseName properties
$linkfiles  = Get-ChildItem -Path $FolderPath -Filter '*.lnk' -File -Recurse -Force |
              Where-Object { $groups.Name -contains $_.BaseName } |
              Group-Object BaseName

# iterate through the grouped *.lnk files
$linkfiles | ForEach-Object {
    $baseName = $_.Name  # the name of the Group is the BaseName of the files in it
    $adGroup = ($groups | Where-Object { $_.Name -eq $baseName }).AD
    # pipe all items in the group through to the Add-NTFSAccess cmdlet
    # see parameter Path at https://ntfssecurity.readthedocs.io/en/latest/Cmdlets/Add-NTFSAccess/
    $_.Group | Add-NTFSAccess -Account $adGroup -AccessRights ReadAndExecute
}

更新

# this is where the output 'log' csv file goes
$outputFile = "C:\Users\adm\Desktop\GroupReport.csv"

# get a list of *.lnk FileIfo objects where the file's BaseName can be found in the
# CSV column 'Name'. Group these files on their BaseName properties
$linkfiles  = Get-ChildItem -Path $FolderPath -Filter '*.lnk' -File -Recurse -Force |
              Where-Object { $groups.Name -contains $_.BaseName } |
              Group-Object BaseName

# iterate through the grouped *.lnk files and add the group permission
# capture the results in a variable $log to output as CSV
$linkfiles | ForEach-Object {
    $baseName = $_.Name  # the name of the Group is the BaseName of the files in it
    $adGroup = ($groups | Where-Object { $_.Name -eq $baseName }).AD

    # create a new access rule
    # see: https://docs.microsoft.com/en-us/dotnet/api/system.security.accesscontrol.filesystemaccessrule
    $rule = [System.Security.AccessControl.FileSystemAccessRule]::new($adGroup, "ReadAndExecute", "Allow")

    $_.Group | ForEach-Object {
        # get the current ACL of the file
        $acl = Get-Acl -Path $_.FullName
        # add the new rule to the ACL
        $acl.SetAccessRule($rule)
        $acl | Set-Acl $_.FullName
        # output for logging csv
        [PsCustomObject]@{
            'Group' = $adGroup
            'File'  = $_.FullName
        }
    }
} | Export-Csv -Path $outputFile -NoTypeInformation

推荐阅读