0

I have a powershell script designed to go through some backup files, archive the month end backup(if its the first of the month) and delete anything older than 9 days after that. I'm trying to tell it to exclude the archive folder but it seems to be ignoring that and I'm unsure why.. kind of a noob to powershell.

I've tried using -notlike $Exlcude+% I've tried -notmatch -NE .. I even tried notcontains even though I knew that wouldn't work.. I tried applying the $exclude to every portion of the code where that folder might be accessed and its still making a copy of it.

#If first of the month copy latest backups to Monthly Backup Folder - will copy full folder path
PARAM($BackupPath="\\SomeServer\sqltestbackups\",
$Exclude= "\\SomeServer\sqltestbackups\Archive")



   #Grab a recursive list of all subfolders
$SubFolders = dir $BackupPath -Recurse | Where-Object {$_.PSIsContainer} | ForEach-Object -Process {$_.FullName}

#Iterate through the list of subfolders and grab the first file in each


$Year = (get-date).Year
$Month = (get-date).Month
$StartOfMonth = Get-Date -Year $Year -Month $Month -Day 1
$Today = (Get-Date).day
$Date = (GET-DATE).AddDays(-9)
$PrevMonth = (GET-DATE).year.ToString()+(Get-Culture).DateTimeFormat.GetMonthName((Get-Date).AddMonths(-1).month)
$Destination=$Exclude + "\" + $Prevmonth +"\"

IF (!(Test-Path -path $destination)) {New-Item $destination -Type Directory}

IF($Today -eq '5')
{
$Path = $BackupPath #Root path to look for files
$DestinationPath = $Destination #Remote destination for file copy

#Grab a recursive list of all subfolders
$SubFolders = dir $Path -Recurse | Where-Object {$_.PSIsContainer -and $_.DirectoryName -notmatch $Exclude} | ForEach-Object -Process {$_.FullName}

#Iterate through the list of subfolders and grab the first file in each
ForEach ($Folder in $SubFolders)
    {
    $FullFileName = dir $Folder | Where-Object {!$_.PSIsContainer -and $_.DirectoryName -notmatch $Exclude} | Sort-Object {$_.LastWriteTime} -Descending | Select-Object -First 1

    #For every file grab it's location and output the robocopy command ready for use
    ForEach ($File in $FullFileName)
        {
        $FilePath = $File.DirectoryName
        $ArchFolder = $File.DirectoryName
        $ArchFolder=$ArchFolder.Replace($BackupPath,"")+"\"
        $FinalPath=$destinationPath+$ArchFolder
        $FileName = $File.Name
        robocopy $FilePath $FinalPath $FileName /A-:SH /R:6 /W:30 /Z 
        }
    }
}


# Delete files older than 9 days that are not contained within the month end folder
Get-ChildItem $BackupPath -Recurse |
  Where-Object { !($_.PSIsContainer) -and
                   $_.LastWriteTime -lt $Date -and
                   $_.Directory -notlike $Exclude+"%" } |
    Remove-Item

The code works except for the copy month end portion.. in this portion it is including the archive folder and I end up with it copying the previous month.. the script is designed to put the files in archive/YM/FullPath of backup so what is happening is its going Archive/YM/ARchive/YM/FullPath even though I'm trying SO HARD to exclude this path from the folders.

Example of whats going wrong with the robocopy

Source : \SomeServer\sqltestbackups\ARCHIVE\2019March\SomeOtherServer\SQLBackups\SomeDatabase\master\

Dest : \SomeServer\sqltestbackups\Archive\2019March\ARCHIVE\2019March\SomeOtherServer\SQLBackups\SomeDatabase\master\

  • If you are just using the default `$exclude` you appear to be adding an extra slash in your string `$Destination=$Exclude + "\" + $Prevmonth +"\"`. Consider using `[io.path]::combine()` when building paths. Its superior to string building. Also `-match` supports regular expressions and slash is a control character so your comparison won't work the same. – Matt Apr 05 '19 at 15:57
  • Please consider providing an [MCVE (Minimal, Complete, and Verifiable Example)](http://stackoverflow.com/help/mcve). – mklement0 Apr 05 '19 at 16:58
  • @Matt looks like you nailed it with that control character, I'm actually returning errors now; I'm not at all familiar with how to use [io.path]::combine() but I'm gonna work through the errors I'm getting now and I'll post back a report later. Thank you! – user11317902 Apr 05 '19 at 17:18
  • Well figured it out.. I needed to double up the \s to get it to work with -notmatch.. all good now:) – user11317902 Apr 05 '19 at 19:07

2 Answers2

0

the type DirectoryInfodoes not have a property DirectoryName. Try property BaseName instead.

# dir, gci are aliases for Get-ChildItem
Get-ChildItem $Path -Recurse `
    | Where-Object { $_.PSIsContainer -and $_.BaseName -notmatch $Exclude }

works.

To see which types are returned and which members there are type

Get-ChildItem .\ | Where-Object { $_.PSIsContainer } | ForEach-Object { $_.GetType() }
# and
Get-ChildItem .\ | Where-Object { $_.PSIsContainer } | Get-Member

But be careful: You will get a lot of output on directories with many files and subdirectories.

Also have a look at the answer How can I exclude multiple folders using Get-ChildItem -exclude? on stackoverflow. This answer comes with lots of elegant solutions for PowerShell from v1.0 to v5.0.

boris
  • 457
  • 2
  • 7
0

problem was

$Exclude= "\\SomeServer\sqltestbackups\Archive" I needed to double up the \s to be

$Exclude= "\\\\SomeServer\\sqltestbackups\\Archive"

after doing this the script worked fine.