Kyle V.
Kyle V.

Reputation: 4782

VBScript - Get newest subfolder that matches pattern

I'm new to VBScript and I'm trying to write code that will return the path to the newest subfolder in a given folder that matches the given naming pattern.

Basically I want it to open the given folder and return the path of the NEWEST subfolder whose name begins with "DevBuild". So for example if the given folder has 3 folders:

DevBuild-14.0  
DevBuild-15.0  
DebugBuild-15.0

I want it to return "{Path to given folder}\DevBuild-15.0\" because it is the newest folder that starts with "DevBuild". By "newest" I mean the folder that has the most recent creation date, OR if it's easier then by the version number. It doesn't matter which.

So far I have this:

Dim fso, folder, subfolders
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder("B:\")
Dim count
count = folder.SubFolders.Count - 1
Dim folderNames()
ReDim folderNames(count)
Set subfolders = folder.SubFolders

'MsgBox UBound(folderNames)

For i = 0 to count
    MsgBox subfolders(i).Name
Next

Unfortunately I am getting an error at the line MsgBox subfolders(i).Name, I think it's because I don't understand how to get an element from the subfolders array.

Upvotes: 1

Views: 1945

Answers (2)

Ekkehard.Horner
Ekkehard.Horner

Reputation: 38745

The starting point for solving problems of getting extrema (the largest, the most recently used, ...) out of a collection (array, folder, ..) should be the idiom/pattern:

  Dim sDir : sDir = "..\data\12203427"
  Dim oSDir
  For Each oSDir In goFS.GetFolder(sDir).SubFolders
      WScript.Echo "Saw:", oSDir.DateCreated, oSDir.Name
  Next

output:

Saw: 30.08.2012 21:42:59 devbuild-15.10
Saw: 30.08.2012 21:43:24 DEVBUILD-15.09
Saw: 30.08.2012 21:44:21 devbuild-9.123
Saw: 30.08.2012 21:31:29 DebugBuild-15.0
Saw: 30.08.2012 21:24:00 DevBuild-14.0

All extra variables (folder, folderNames, ...) are error-prone fat.

To get the 'last' subfolder using .DateCreated, just weave in

  1. a date to keep track of the .DateCreated of the newest folder seen (initialized to a small out-of-possible-range date)
  2. an If statement to record the newest folder so far

To filter the folders according to name/prefix, add

  1. the prefix and its length
  2. an If statement to avoid non-matching folder(names)

In code:

  Dim sDir     : sDir      = "..\data\12203427"
  Dim dtMR     : dtMR      = #1/1/1970#
  Dim sMRDir   : sMRDir    = ""
  Dim sPfx     : sPfx      = "devbuild-"
  Dim nPfx     : nPfx      = Len(sPfx)
  Dim oSDir
  For Each oSDir In goFS.GetFolder(sDir).SubFolders
      WScript.Echo "Saw:", oSDir.Name
      If 0 = StrComp(sPfx, Left(oSDir.Name, nPfx), vbTextCompare) Then
         WScript.Echo Space(4), "DC:", oSDir.DateCreated
         If dtMR < oSDir.DateCreated Then
            dtMR   = oSDir.DateCreated
            sMRDir = oSDir.Name
         Else
            WScript.Echo Space(4), "older then", dtMR
         End If
      Else
         WScript.Echo Space(4), "does not start with", sPfx
      End If
  Next
  WScript.Echo "-----------"
  If "" = sMRDir Then
     WScript.Echo "no subfolder found"
  Else
     WScript.Echo "found", sMRDir, dtMR
  End If

output:

Saw: devbuild-15.10
     DC: 30.08.2012 21:42:59
Saw: DEVBUILD-15.09
     DC: 30.08.2012 21:43:24
Saw: devbuild-9.123
     DC: 30.08.2012 21:44:21
Saw: DebugBuild-15.0
     does not start with devbuild-
Saw: DevBuild-14.0
     DC: 30.08.2012 21:24:00
     older then 30.08.2012 21:44:21
-----------
found devbuild-9.123 30.08.2012 21:44:21

To rely on the folder name's version, follow the same strategy, but use appropriate data types (double version, RegExp filter and extractor):

  Dim sDir     : sDir      = "..\data\12203427"
  Dim dblMR    : dblMR     = -1.0
  Dim sMRDir   : sMRDir    = ""
  Dim reCut    : Set reCut = New RegExp
  reCut.IgnoreCase = True
  reCut.Pattern    = "^DevBuild-(\d+\.\d+)$"
  Dim oSDir
  For Each oSDir In goFS.GetFolder(sDir).SubFolders
      WScript.Echo "Saw:", oSDir.Name
      Dim oMTS : Set oMTS = reCut.Execute(oSDir.Name)
      If 1 = oMTS.Count Then
         Dim dblCVers : dblCVers = CDbl(oMTS(0).SubMatches(0))
         WScript.Echo Space(4), "Version:", dblCVers
         If dblMR  < dblCVers Then
            dblMR  = dblCVers
            sMRDir = oSDir.Name
         Else
            WScript.Echo Space(4), "older then", dblMR
         End If
      Else
         WScript.Echo Space(4), "does not match", reCut.Pattern
      End If
  Next
  WScript.Echo "-----------"
  If "" = sMRDir Then
     WScript.Echo "no subfolder found"
  Else
     WScript.Echo "found", sMRDir, dblMR
  End If

output:

Saw: devbuild-15.10
     Version: 15,1
Saw: DEVBUILD-15.09
     Version: 15,09
     older then 15,1
Saw: devbuild-9.123
     Version: 9,123
     older then 15,1
Saw: DebugBuild-15.0
     does not match ^DevBuild-(\d+\.\d+)$
Saw: DevBuild-14.0
     Version: 14
     older then 15,1
-----------
found devbuild-15.10 15,1

(!german locale!)

Upvotes: 1

Nilpo
Nilpo

Reputation: 4816

Some of your code is a little redundant. Here's how I would do this. Notice the For Each block.

Dim fso, folder, subfolders, subfolder
Set fso = CreateObject("Scripting.FileSystemObject")
Set folder = fso.GetFolder("B:\")

Set subfolders = folder.SubFolders

Dim folderNames(subfolders.Count)

dim i
i = 0
For Each subfolder in subfolders
    folderNames(i) = subfolder.Name
    i = i + 1
Next

Upvotes: 0

Related Questions