2015-09-09 22 views
3

我有一個非常大的文件夾列表,我需要從每個文件夾中刪除一個ACL。我試圖編寫一個腳本來在很短的時間內完成它,但我遇到了一些麻煩。如何從一大組文件夾中刪除單個用戶ACL?

這是我到目前爲止有:

$filepath = "C:\ALCTEST" 
$user = "domain\username" 

$folders = @((get-item $filePath)) 
$folders += Get-ChildItem $filePath -Recurse | 
      where { $_.PSIsContainer -ne $false } 

##Need to do this in order to remove item 0 from the array, otherwise 
##item 0 is the parent folder 
$newfolders = $folders[1,2 + 3..($folders.length - 1)] 

foreach ($folder in $newfolders) { 
    $acl = Get-Acl -Path $folder.FullName 

    foreach ($access in $acl.access) { 
     foreach ($value in $access.IdentityReference.Value) { 
      if ($value -eq $user) { 
       $acl.RemoveAccessRule($access) | Out-Null 
      } 
     } 
    } 

    Set-Acl -Path $folder -AclObject $acl 
} 

從我的調試過程中的注視下,我覺得一切作品的權利,直到我嘗試設置ACL放回文件夾。當它到達該行時,出現錯誤

找不到路徑'C:\ Windows \ system32 \ 01',因爲它不存在。

ACLTEST的父文件夾內有七個名爲「01」...「07」的文件夾,各種ACL用於測試。

我不確定該從哪裏出發。我正在閱讀this Scripting Guy article,它幫助我度過了很多,但他的腳本似乎專注於手動輸入文件夾路徑,對於需要更改的幾百個文件夾,我絕對無法做到這一點。

任何幫助表示讚賞。我是PowerShell腳本的新手,所以如果您發現除了我在上面的腳本中提到的錯誤之外的其他錯誤,我很樂意聽到他們的聲音。

回答

5

Set-Acl的參數-Path需要一個路徑字符串,而不是DirectoryInfo對象。當傳遞後者時,只有Name屬性被展開,因此Set-Acl正在當前工作目錄中尋找具有給定名稱的對象(在您的案例中顯然爲C:\Windows\system32)。

變化

Set-Acl -Path $folder -AclObject $acl 

Set-Acl -Path $folder.FullName -AclObject $acl 

,問題就會消失。

就這樣說,你也可以做一些其他的修改。

$folders = @((get-item $filePath)) 
$folders += Get-ChildItem $filePath -Recurse | 
      where { $_.PSIsContainer -ne $false } 

##Need to do this in order to remove item 0 from the array, otherwise 
##item 0 is the parent folder 
$newfolders = $folders[1,2 + 3..($folders.length - 1)] 

如果你不想數組中的父文件夾:不要把它在數組中的首位。由於您顯然擁有PowerShell v3,因此您可以使用-Directory參數而不是where過濾器。

$newfolders = Get-ChildItem $filePath -Recurse -Directory 
foreach ($access in $acl.access) { 
    foreach ($value in $access.IdentityReference.Value) { 
     if ($value -eq $user) { 
      $acl.RemoveAccessRule($access) | Out-Null 
     } 
    } 
} 

每個接入規則僅具有單個身份引用,所以內循環是毫無意義的。

foreach ($access in $acl.access) { 
    if ($access.IdentityReference.Value -eq $user) { 
     $acl.RemoveAccessRule($access) | Out-Null 
    } 
} 

你的代碼可以精簡到這樣的事情:

$filepath = 'C:\ALCTEST' 
$user  = 'domain\username' 

$folders = Get-ChildItem $filePath -Recurse -Directory 

foreach ($folder in $folders) { 
    $acl = Get-Acl -Path $folder.FullName 

    foreach ($access in $acl.Access) { 
     if ($access.IdentityReference.Value -eq $user) { 
      $acl.RemoveAccessRule($access) | Out-Null 
     } 
    } 

    Set-Acl -Path $folder.FullName -AclObject $acl 
} 

或(使用管道)是這樣的:

$filepath = 'C:\ALCTEST' 
$user  = 'domain\username' 

Get-ChildItem $filePath -Recurse -Directory | ForEach-Object { 
    $acl = Get-Acl -Path $_.FullName 

    $acl.Access | Where-Object { 
     $_.IdentityReference.Value -eq $user 
    } | ForEach-Object { 
     $acl.RemoveAccessRule($_) | Out-Null 
    } 

    Set-Acl -Path $_.FullName -AclObject $acl 
} 
+0

非常感謝您!這正是我正在尋找的,因爲我知道我的代碼可能不是最好的。 –

相關問題