1

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
    }
mklement0
  • 382,024
  • 64
  • 607
  • 775
Thomas BP
  • 1,187
  • 3
  • 26
  • 62
  • What is the reason you use `$_.Name -match '.+software$|^software.+'` instead of `$_.Name -like 'softwaretest'`? – Paxz Dec 23 '17 at 14:26
  • Hi Paxz.. me and regular exp./RegEX. :-) the last expression will return true for software, right ? it will not work for backupsoftware and softwarebackup, right? - the elseif statement needs to look after folders that have the software included in the name, but not the standalone word software, if there is no names including software.. then run elseif - then word/letters before and after "software" can be any word/letters, softwaretest was just an example. – Thomas BP Dec 23 '17 at 15:22

2 Answers2

2

I find it very confusing, to have the negation on the right or even in the RegEx. I think it would be more obvious, to negate in the beginning with a ! or -not.

To test, if a folder exist, you can use Test-Path. Test-Path also has a -Filter parameter, which you can use instead of Where-Object. But I think you don't even have to filter.

$SoftwarePath = "$($Env:SystemRoot)\Software", "$($Env:SystemRoot)\SoftwareBackup"

foreach ($Path in $SoftwarePath) {
    if (Test-Path -Path $Path) {
        Remove-Item -Path $Path -Force -Verbose
    }
    else {
        Write-Output "$Path not found."
    }
}   

Would that work for you?

vrdse
  • 2,899
  • 10
  • 20
  • that could work, but SoftwareBackup is just a name, it could be anything else, like *software* or ^software* or *software$. the only role is that it can't be ^software$ – Thomas BP Dec 23 '17 at 18:00
0

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.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • Hi mklement0 - That is working and give me the right values of the folder TRUE/FALSE, so I will build an IF-statement for that code, so I'm getting the if, elseif and else. and then add an -exclude for the $folders for the CSC and System32 folder, because I'm getting some access denied.... so fare THX. and a happy Christmas to you. ... but can see that i can't add an -Exclude for the same codeline as the -Include. – Thomas BP Dec 24 '17 at 15:04
  • Glad to hear it. As for `-Exclude`: In general, you should be able to do combine `-Include` with `-Exclude`. – mklement0 Dec 24 '17 at 16:22
  • Yes have tried with and $excludewildcard = 'csc', 'system32' - but I'm still getting the access denied for both folders... – Thomas BP Dec 24 '17 at 16:50
  • I see: By the time `-Exclude` is applied, the access-denied errors have already happened. Please see my update, which now uses `Get-Item` instead of `Get-ChildItem` to prevent this problem. – mklement0 Dec 24 '17 at 17:38