Using DirectoryInfo.GetFiles instead of Directory.GetFiles, advanced filtering

Most times it’s recommended to use Directory.GetFiles to get the files in a folder. I’ve found DirectoryInfo.GetFiles to be more useful. It gets the files as an IEnumerable of FileInfo, which makes filtering easier and gives you more info about the files. You can later For Each through it and get any of the attributes of the file you want: filename (currentItem.Name); extension (currentItem.Extension), full path and filename (currentItem.FullName) etc. Here is the full definition of FileInfo with a property listing:

Here is a reference to the DirectoryInfo.GetFiles method:

Now for some advanced filtering. There are some inputs stored in variables (coming from a source file):

  • currentPath (path to the folder)
  • FileSearchPattern (standard filter with * and ? wildcards for filename, ie test will find any file with test in the filename
  • Extensions (array of extensions to filter for; ie {.txt,.xlsx} will find text and JSON files)
  • TimeOperator (options EXACT, AFTER, or BEFORE to control date filtering)
  • FilterDate (a previously calculated datetime to use for finding the files)

One of the keys here is that FileSearchPattern, Extensions, and TimeOperator can be empty so we need a way to nullify those parts of the filter. That is done with a simple OR operator:

Function(s) (Extensions.Contains(s.Extension.ToUpper) OR String.IsNullOrEmpty(String.Join(",",Extensions)))

What that means is if the Extensions array is empty, the Extensions.Contains doesn’t matter, but if the Extensions array has items in it, then the Extension.Contains is what matters.

We can do something similar with the TimeOperator. It can be EXACT, AFTER, BEFORE, or blank, so we need to account for those four possibilites:

(
  (TimeOperator = "EXACT" AND s.LastWriteTime.Date = FilterDate.Date)
OR
  (TimeOperator = "BEFORE" AND s.LastWriteTime.Date < FilterDate.Date)
OR
  (TimeOperator = "AFTER" AND s.LastWriteTime.Date > FilterDate.Date)
OR (String.IsNullOrEmpty(TimeOperator))
)

That last line is the one that accounts for TimeOperator not being provided, nullifying the previous three filters. Each of the first three filters uses an AND, so that only the one that matches the value of TimeOperator is used (ie >, <, or =)

Put the whole thing together and you have a single statement with Switch functionality built in:

image

New System.IO.DirectoryInfo(currentPath).GetFiles(FileSearchPattern).OrderByDescending(Function (d) d.LastModifiedDate).Where(Function(s) (Extensions.Contains(s.Extension.ToUpper) OR String.IsNullOrEmpty(String.Join(",",Extensions))) And ((TimeOperator = "EXACT" AND s.LastWriteTime.Date = FilterDate.Date) OR (TimeOperator = "BEFORE" AND s.LastWriteTime.Date < FilterDate.Date) OR (TimeOperator = "AFTER" AND s.LastWriteTime.Date > FilterDate.Date) OR (String.IsNullOrEmpty(TimeOperator))))

One of the keys is that you have to put New before it, because System.IO.DirectoryInfo is a class type.

Note that currentPath and FileSearchPattern are not both properties of DirectoryInfo, you provide the path to DirectoryInfo and the filename filter to GetFiles.

For the date comparisons I’m using .Date - this ensures that time is irrelevant. For example, if Now is 8/19/2023 4:27PM, then Now.Date (or Today.Date, LastWriteTime.Date) become 8/19/2023 00:00:00 which is the beginning of the day. Therefore “LastWriteTime.Date = Today.Date” will pull anything for today, without the time affecting the comparison.

I’m also sorting the files descending by LastWriteTime.Date because there is an additional value TakeXFiles that can contain an integer, determining how many files are kept from the above filter.

fileInfoCollection.Take(CInt(transactionItem.SpecificContent("Latest X Files").ToString))

2 Likes