I have 2 folders in my windows folder, software, and softwaretest. So I have the main folder "software" if statement, then jump to the elseif - here I have the backup folder, so jump to the else...
my problem is that I'm getting the write-host from the elseif, and I have a backup folder that I'm calling softwaretest, so can't see why it give me that output and not the else.
hope someone can guide/help me :-)
If ($SoftwarePathBackup = Get-ChildItem -Path "$Env:SystemRoot" | Where-Object { (!$_.Name -like 'software') }) {
Write-Host ( 'There are no folder named \software\ on this machine - You cant clean/clear/empty the folder!' ) -ForegroundColor Red;
} elseif ($SoftwarePathBackup = Get-ChildItem -Path "$Env:SystemRoot" | Where-Object { ($_.Name -match '.+software$|^software.+') } | Sort-Object) {
Write-Host ( 'There are none folder-backups of \software\ on this machine - You need to make a folder-backup of \software\ before you can clean/clear/empty the folder!' ) -ForegroundColor Red;
} else {
Remove-Item
}
Your primary problem is one of operator precedence:
!$_.Name -like 'software'
should be ! ($_.Name -like 'software')
or, preferably,
$_.Name -notlike 'software'
- using PowerShell's not
-prefixed operators for negation.
Similarly, you probably meant to negate $_.Name -match '.+software$|^software.+'
which is most easily achieved with $_.Name -notmatch '.+software$|^software.+'
As stated in Get-Help about_Operator_Precedence
, !
(a.k.a. -not
) has higher precedence than -like
, so !$_.Name -like 'software'
is evaluated as (!$_.Name) -like 'software'
, which means that the result of !$_.Name
- a Boolean - is (string-)compared to wildcard pattern 'software'
, which always returns $False
, so the If
branch is never entered.
That said, you can make do without -like
and -match
altogether and use the implicit wildcard matching supported by Get-Item
's -Include
parameter (snippet requires PSv3+):
# Get folders whose name either starts with or ends with 'software', including
# just 'software' itself.
$folders = Get-Item -Path $env:SystemRoot\* -Include 'software*', '*software' |
Where-Object PSIsContainer
# See if a folder named exactly 'software' is among the matches.
$haveOriginal = $folders.Name -contains 'software'
# See if there are backup folders among the matches (too).
# Note that [int] $haveOriginal evaluates to 1 if $haveOriginal is $True,
# and to 0 otherwise.
$haveBackups = ($folders.Count - [int] $haveOriginal) -gt 0
# Now act on $folders as desired, based on flags $haveOriginal and $haveBackups.
Note how Get-Item -Path $env:SystemRoot\*
is used to explicitly preselect all items (add -Force
if hidden items should be included too), which are then filtered down via -Include
.
Since Get-Item
- unlike Get-ChildItem
- doesn't support -Directory
, | Where-Object PSIsContainer
is used to further limit the matches to directories (folders).
Note: Get-ChildItem
was not used, because -Include
only takes effect on child (descendant) items (too) when -Recurse
is also specified; while -Recurse
can be combined with -Depth 0
(PSv3+) in order to limit matching to immediate child directories, Get-ChildItem
apparently still tries to read the entries of all child directories as well, which can result in unwanted access-denied errors from directories that aren't even of interest.
In other words: Get-ChildItem -Recurse -Depth 0 -Directory $env:SystemRoot -include 'software*', '*software'
is only equivalent if you have (at least) read access to all child directories of $env:SystemRoot
.