I have a Powershell script that selects a random file in a lab environment and then reads, writes, creates, and deletes files to simulate a live environment. This lab also includes folders that I don't have access to. When I perform these file actions I pick a folder at random, which can sometimes be a folder that I don't have access to. In order to ensure that I have selected a random folder that is both (a) accessible and (b) contains files, I run the following code:
function Get-RandomAccessibleFile {
param(
[Parameter(ValueFromPipeline)][ValidateNotNullOrEmpty()][System.Collections.ArrayList]$Folders
)
do {
$RandomFolder = $Folders | Get-Random
$RandomFiles = Get-ChildItem $RandomFolder -File -ErrorAction SilentlyContinue
} until ($RandomFiles)
$RandomFile = $RandomFiles | Get-Random
return $RandomFile
}
This works, but I now find myself in a situation where I need to only validate if the folder can be accessed. This means that the Get-ChildItem
could potentially run successfully, but if the randomly selected folder is empty, the $RandomFiles
variable will become $null
and my script would keep running until it finds a folder that currently contains files (and removing the -File
flag isn't enough as it can be a completely empty folder without any subfolders). The only way I have found to guarantee that I find a folder that I have access to is to check the Acl with Get-Acl
like so:
function Get-RandomAccessibleFolder {
param(
[Parameter()][ValidateNotNullOrEmpty()][System.Collections.ArrayList]$Folders
)
do {
$RandomFolder = $Folders | Get-Random
$FolderIsAccessible = Get-ChildItem $RandomFolder -ErrorAction SilentlyContinue
if (-not $FolderIsAccessible) {
try {
Get-Acl -Path $RandomFolder -ErrorAction Stop > $null
$FolderIsAccessible = $true
}
catch {
$null
}
}
} until ($FolderIsAccessible)
return $RandomFolder
}
This feels super-inefficient. If I don't have access to the folder the first Get-ChildItem
will fail, and then I run the Get-Acl
again which I know will fail. I would only need to check the Get-Acl if the Get-ChildItem
succeeded AND the result is empty.