2

I'm very new to bat scripting and would like to be able to do the following:

I have a main 'backups' folder which in turn contains unique folders for individual daily backups taken (i.e. named 'backup (date/time'). Within these individual daily backup folders they contain both files and folders.

I would therefore like to be able to check the main 'backups' folder and if the size is greater then say 50GB then the oldest folder and anything contained within is deleted.

I came across the script below in the Forum which does what I'm looking for, but on files rather then folders. Due to my elementally level of scripting, I'm not sure how straightforward it would be to adapt have it work with folders or if there is something else already available.

Many Thanks

Set fso = CreateObject("Scripting.FileSystemObject")
Set F = fso.GetFolder("C:\Users\User\Desktop\New Folder\Stories\Test")

If F.size > 2^30*2 Then

'Comments on a stupid editor that can't handle tabs
        'Creating an in memory disconnected recordset to sort files by date
    Set rs = CreateObject("ADODB.Recordset")
    With rs
        .Fields.Append "Date", 7 
        .Fields.Append "Txt", 201, 5000 
        .Open

        For Each Thing in f.files
            .AddNew
            .Fields("Date").value = thing.datelastmodified
            .Fields("Txt").value = thing.path
            .UpDate
        Next
        .Sort = "Date Desc"
        Do While not .EOF
            fso.deletefile  .Fields("Txt").Value
            If f.size < 2^30*2 then Exit Do
            .MoveNext
        Loop
    End With
End If
Richard
  • 75
  • 7
  • Do not add the `batch-file` tag again, this is `vbs` not batch file. – Gerhard Oct 09 '19 at 12:01
  • If you look up `FileSystemObject`, you will see that you can also iterate through Folders (`For Each objFolder In fso.GetFolder("C:\Users\User\Desktop\New Folder\Stories\Test").SubFolders`). If you do that, you can use this code to sum up the size of all files in the folder. Try it out and post your code so we can help you out. – Étienne Laneville Oct 09 '19 at 16:15
  • Thank you for this and information which I am currently researching . . . as mentioned my skill level is somewhat rudimentary, so it may take time ! – Richard Oct 10 '19 at 14:30

2 Answers2

1

Here's code that does what you are looking for:

Dim objFSO

PurgeBackups "C:\Temp"

Sub PurgeBackups(p_sRootFolder)
    Dim objRootFolder
    Dim objOldestFolder
    Dim fOldestInitialized
    Dim objFolder
    Dim lngFolderSize

    Set objFSO = CreateObject("Scripting.FileSystemObject")
    Set objRootFolder = objFSO.GetFolder(p_sRootFolder)
    fOldestInitialized = False

    For Each objFolder In objRootFolder.SubFolders

        lngFolderSize = GetFolderSize(objFolder)

        If lngFolderSize > 50000000000# Then

            ' Decide if you want to delete this Folder or not
            If Not fOldestInitialized Then
                Set objOldestFolder = objFolder
                fOldestInitialized = True
            End If

            ' Compare date
            If objFolder.DateCreated < objOldestFolder.DateCreated Then
                Set objOldestFolder = objFolder
            End If

        End If

    Next

    If fOldestInitialized Then
        ' Delete oldest folder
        objOldestFolder.Delete
    End If

End Sub    

Function GetFolderSize(p_objFolder)
    Dim objFile
    Dim objFolder
    Dim lngFolderSize

    lngFolderSize = 0

    For Each objFile In p_objFolder.Files
        lngFolderSize = lngFolderSize + objFile.Size
    Next

    For Each objFolder In p_objFolder.SubFolders
        lngFolderSize = lngFolderSize + GetFolderSize(objFolder)
    Next

    GetFolderSize = lngFolderSize

End Function
Étienne Laneville
  • 4,697
  • 5
  • 13
  • 29
  • Thank you very much for this, and very appreciate it . . . I must apologise for the delay in getting back, but as mentioned I’m pretty much a novice, so I’m still trying to get my head around your script, and how to go about amending it to Delete the oldest folder on reaching the preset limit.So, apologies for my slow-wittedness. – Richard Oct 10 '19 at 14:24
  • You can keep a reference to the last folder that was found to be over your limit. Then, when you find a new one, you can compare their dates. If the new one is older, set your reference to that one. At the end you should have a reference to the oldest folder. – Étienne Laneville Oct 10 '19 at 14:42
  • Check out updated answer, it does everything you need. I hope you learn from this example, don't expect users on Stack Overflow to write code for you. Sometimes they will but don't count on it. – Étienne Laneville Oct 10 '19 at 16:06
  • Thank you very much for this script, sorry for any misunderstanding, my intention was far from ‘expecting users on Stack Overflow to write code’, but as I’m in the early days of scripting it takes me a tad longer to get to grips with things. I do appreciate what you have done, and will defiantly learn from it. – Richard Oct 12 '19 at 13:48
  • Regards the script: the extra ‘#’ was obviously put in there, just to test me ! – Richard Oct 12 '19 at 13:48
  • Please check out my attempt below, which I would welcome your comment. – Richard Oct 12 '19 at 13:48
  • Using `objFolder.Size` is a better approach but my `GetFolderSize` function is a good example of using recursion (function or sub calling itself). There's plenty of ready-to-use VBScript code out there. As you integrate some of it in your code, take the time to notice things like that. – Étienne Laneville Oct 12 '19 at 16:16
1

Please find below my attempt which has been based on an existing script and modified to suit, with a few extra flurries . . . I would be grateful for comment.

strOldestFolder = ""
dtmOldestDate = Now

Set oShell = CreateObject("WScript.Shell")
strHomeFolder = oShell.ExpandEnvironmentStrings("%USERPROFILE%\HDBackups")

Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFolder = objFSO.GetFolder(strHomeFolder)

intFolderSize = Int((objFolder.Size / 1024) / 1024)

If intFolderSize >= 50 Then ' change as appropriate, value in MBytes
    Set objSubFolders = objFolder.SubFolders
    For Each objFolder in objSubFolders
        strFolder = objFolder.Path
        dtmFolderDate = objFolder.DateCreated
        If dtmFolderDate < dtmOldestDate Then
            dtmOldestDate = dtmFolderDate
            strOldestFolder = strFolder
        End If
    Next
    objFSO.DeleteFolder(strOldestFolder)
End If

One aspect that I'm not entirely happy with is the look and neatness of the 'str' and 'Set' in the first six code lines, I would like to be group them together, i.e. all the Sets together. But so far have been unable to do so without the script failing.

Note: have used 50MB rather then the 50GB as per original description, makes testing a bit easier.

Richard
  • 75
  • 7
  • Script looks fine, I wouldn't worry about the aesthetics as long as variables are well named and the structure is good. You can use functions and subroutines to bundle certain things like getting your Home folder (that can be a function). – Étienne Laneville Oct 12 '19 at 15:01
  • Check out Code Review on Stack Exchange, it's a better place for conversations about working code. – Étienne Laneville Oct 12 '19 at 15:05
  • Many thanks . . . one additional thing if I may. Cleary the script/s check the total ‘size’ of everything within the ‘main folder’, which may contain a combination of both Folders and Files at the same folder level. But if I wished to only acquire the size of the folders (plus everything they contain) within the main folder, i.e. excluding the files at the same level, is there a relatively straightforward way of doing this (maybe objFolder.Attributes) ? – Richard Oct 13 '19 at 13:44
  • P.S. I not sure of the etiquette on this forum as to whether I should open this as a completely new Question, or to continue within this one ! – Richard Oct 13 '19 at 13:45
  • My script does exactly that, it doesn't include files in root folder, just the subfolders. You can start new questions from this point on since this question has been answered. You will probably get different people looking at your question which might bring new approaches. – Étienne Laneville Oct 13 '19 at 15:59
  • Forum Note: Please refer also to the enhanced version of this script: 'Getting the Folder size for only subfolders, whist ignoring any other content?' (https://stackoverflow.com/questions/58367723/getting-the-folder-size-for-only-subfolders-whist-ignoring-any-other-content). – Richard Oct 16 '19 at 15:40