I had a similar problem with set-acl and square brackets. I tried converting the path to a string first and then passed it as a variable to set-acl, with the path wrapped in quotes.
$itempath = $item.FullName.ToString()
Set-Acl -path "$itempath" -aclObject $acl
The behavior changed to no errors, but upon closer inspection items with special characters had everything but the ownership changed(!?)
set-acl bug? :-/
I tested with a directory with 10 subdirectories. 8 of them had the same name as valid domain users, and the other two had names that didn't match users, including one with funky characters.
In the valid user folders were tons of files and subdirectories. Of these, 3 contained both directories and files with funky characters at various levels of the hierarchy.
I put quite a bit of data in these to get an idea of ps resource usage before I set the script loose on a whole terabyte of data.
My script leans on the PowerShell Community Extensions.
Last thoughts before I go home to sleep - regex the string and insert ticks before the illegal chars. Embedded .replace() would suck. What a hack.
This is my first script, so please give me feedback. Any in-the-box ideas how to handle the special characters?
I'm hoping someone might find this useful too..
Full script:
$workdir = "Z:\TEST\"
$workdom = "domain.dom"
$workdomshort = "DOMAIN"
# we skip directories beginning with underscore character
$paths = ( Get-ChildItem $workdir -Exclude "_*" )
# validate before we begin
# todo: test domain, test path
Write-Host "Working directory is: $workdir"
Write-Host "Working domain is: $workdom"
$bail = Read-Host -Prompt "Continue? [y/n]"
if ( $bail -ne "y" ) { exit 0 }
Set-Location -path $workdir
#PSCX trick to allow change ownership to different user
$SeRestore = New-Object Pscx.Interop.TokenPrivilege "SeRestorePrivilege", $true
Set-Privilege $SeRestore
# scan profile directories and set ownership for each
foreach ( $path in $paths )
{
Write-Host "** Examining " -NoNewline
Write-Host -backgroundcolor red "[ $path ]" -nonewline
Write-Host " and contents...**"
# extract the short name of the path
# which should be the same as the owner
$ownedby = ( Split-Path -leaf $path.Name )
if ( ( get-adobject -value $ownedby ) -ne $null )
{
Write-Host "User: " -nonewline
Write-Host -backgroundcolor red $ownedby -nonewline
Write-Host " exists!"
#
## set up acl
Write-Host "Building ACL... " -NoNewline
$acl = Get-Acl -path $path # start with existing ACL
#
## define user access, inheritance, propagation
$principal = "$workdomshort\$ownedby"
$inheritance = [System.Security.AccessControl.InheritanceFlags]::ContainerInherit -bor [System.Security.AccessControl.InheritanceFlags]::ObjectInherit
$propagation=[System.Security.AccessControl.PropagationFlags]::None
$args = $principal, "Modify", $inheritance, $propagation, "Allow"
$accessrule = New-Object System.Security.AccessControl.FileSystemAccessRule $args
$acl.SetAccessRule($accessrule)
#
## define ownership
$account = New-Object System.Security.Principal.NTAccount("$workdomshort","$ownedby")
$acl.SetOwner($account)
#
Write-Host "done."
#
# do it to parent first
Write-Host "Applying ACL to profile directory... " -NoNewline
Set-Acl -Path $path -AclObject $acl
Write-Host " done."
#
# now do it, all recursive-like
$items = ( Get-ChildItem -Recurse -Path $path )
Write-Host "Applying ACL to profile directory contents..." -NoNewline
if ( $items -ne $null )
{
foreach ( $item in $items )
{
$itempath = $item.FullName.ToString()
Set-Acl -path "$itempath" -aclObject $acl
Write-Host "." -nonewline
}
Write-Host " done!"
Write-Host ( $items.count ) " items modified."
Write-Host
}
else
{
# in case of empty profile
Write-Host "n/a"
Write-Host
}
}
else
{
# bogus user, rename directory
Write-Host "User: $owndedby does not exist! `a"
$pathbad = ( "_" + "$ownedby" )
Write-Host -backgroundcolor RED "Renaming $path to $pathbad"
ren $path $pathbad
Write-Host
}
}