Iterating through a list of folders

Hello all,

SUper Noob here. I have a very basic question regarding iteration through a list of folders that I need to search. The object of this program is to look for files older then 10 days old in a given set of folders. As much as I dont mind doing if statements for each folder object I specified, I would like to be able to grow the list and not have excessive code. Anyway, any and all suggestions would be greatly appcriciated. Thank you and take care.

This is what I have now:

Sub Main()

Dim fso, Efile, EFolder1, Efolder2

fso = CreateObject("Scripting.FileSystemObject")

EFolder1 = fso.getfolder("C:\temp2")

Efolder2 = fso.getfolder("C:\temp3")

For Each Efile In Efolder2

If DateDiff("d", Efile.datelastmodified, Now) > 10 Then

Efile.delete()

End If

Next

Efile = Nothing

For Each Efile In EFolder1

If DateDiff("d", Efile.datelastmodified, Now) > 10 Then

Efile.delete()

End If

Nex

End Sub

NOTE : I tried using the "collection class" to store the efolder objects, however was not able to loop through the collection.



Answer this question

Iterating through a list of folders

  • ProjectDev

    ok lets see - we need to clean up your code!

    Why are you creating an fso Why dont you use the System.IO.Directory.GetDirectories() or GetFiles() class

    Dim theFolders() as String = System.IO.Directories.GetDirectories("Path")

    Dim theFilesToDelete as new ArrayList()

     

    for each currentFolder as String in theFolders

       Dim theFilesInCurrentFolder() as String = System.IO.Directories.GetFiles(currentFolder)

     

       for each currentFile as String in theFilesInCurrentFolder

          'get the LastAccessTime of the file

          Dim theFileInfo as new FileInfo(currentFile)

          'If statement goes here to check the LastAccessTime of the File and see if its 10 days or more from today's date

             theFilesToDelete.Add(currentFile)

          end if     

       next

    next

     

    for each currentFile as String in theFilesToDelete

       System.IO.File.Delete(currentFile)

    next

     

    does this help/make you understand better



  • IceAngel89

    I think that your proposed method of passing the folder names is on target. I would extend it just a tad though... I would create a class to represent each folder (folder path, sub directories option, search pattern option). I would make that class serializable so that the list of folders can be easily saved to/read from disk. Then I would create a List(of T) collection to hold each folder item class object. This list can the be bound to by controls in the UI.

    Following is a simple little example application. To try it, start a new Windows Application project. In the Solution Explorer, click the Show All Files button, expand Form1, and open the Form1.Designer.vb code file. You can then paste the section of code below marked Form1.Designer.vb over what is already there. This will layout the form for you. Don't worry about this code too much as it is just what the designer generates as you drag controls onto a form and set their properties.

    After you've got the form layout, paste the rest of the code into the Form1.vb code file. This example will demonstrate some simple yet very useful concepts such as object databinding and serialization.

    Form1.Designer.vb – This code just sets up the form

    <Global.Microsoft.VisualBasic.CompilerServices.DesignerGenerated()> _

    Partial Class Form1

    Inherits System.Windows.Forms.Form

    'Form overrides dispose to clean up the component list.

    <System.Diagnostics.DebuggerNonUserCode()> _

    Protected Overrides Sub Dispose(ByVal disposing As Boolean)

    If disposing AndAlso components IsNot Nothing Then

    components.Dispose()

    End If

    MyBase.Dispose(disposing)

    End Sub

    'Required by the Windows Form Designer

    Private components As System.ComponentModel.IContainer

    'NOTE: The following procedure is required by the Windows Form Designer

    'It can be modified using the Windows Form Designer.

    'Do not modify it using the code editor.

    <System.Diagnostics.DebuggerStepThrough()> _

    Private Sub InitializeComponent()

    Me.components = New System.ComponentModel.Container

    Me.FoldersListBox = New System.Windows.Forms.ListBox

    Me.NewPathTextBox = New System.Windows.Forms.TextBox

    Me.BrowseButton = New System.Windows.Forms.Button

    Me.FolderBrowserDialog1 = New System.Windows.Forms.FolderBrowserDialog

    Me.AddButton = New System.Windows.Forms.Button

    Me.RemoveButton = New System.Windows.Forms.Button

    Me.ExecuteButton = New System.Windows.Forms.Button

    Me.SubFoldersCheckBox = New System.Windows.Forms.CheckBox

    Me.Label1 = New System.Windows.Forms.Label

    Me.PatternTextBox = New System.Windows.Forms.TextBox

    Me.BindingSource1 = New System.Windows.Forms.BindingSource(Me.components)

    CType(Me.BindingSource1, System.ComponentModel.ISupportInitialize).BeginInit()

    Me.SuspendLayout()

    '

    'FoldersListBox

    '

    Me.FoldersListBox.FormattingEnabled = True

    Me.FoldersListBox.Location = New System.Drawing.Point(12, 94)

    Me.FoldersListBox.Name = "FoldersListBox"

    Me.FoldersListBox.Size = New System.Drawing.Size(368, 173)

    Me.FoldersListBox.TabIndex = 0

    '

    'NewPathTextBox

    '

    Me.NewPathTextBox.Location = New System.Drawing.Point(13, 16)

    Me.NewPathTextBox.Name = "NewPathTextBox"

    Me.NewPathTextBox.Size = New System.Drawing.Size(285, 20)

    Me.NewPathTextBox.TabIndex = 1

    '

    'BrowseButton

    '

    Me.BrowseButton.Location = New System.Drawing.Point(305, 16)

    Me.BrowseButton.Name = "BrowseButton"

    Me.BrowseButton.Size = New System.Drawing.Size(75, 23)

    Me.BrowseButton.TabIndex = 2

    Me.BrowseButton.Text = "Browse"

    Me.BrowseButton.UseVisualStyleBackColor = True

    '

    'AddButton

    '

    Me.AddButton.Location = New System.Drawing.Point(12, 66)

    Me.AddButton.Name = "AddButton"

    Me.AddButton.Size = New System.Drawing.Size(115, 23)

    Me.AddButton.TabIndex = 3

    Me.AddButton.Text = "Add Path"

    Me.AddButton.UseVisualStyleBackColor = True

    '

    'RemoveButton

    '

    Me.RemoveButton.Location = New System.Drawing.Point(133, 66)

    Me.RemoveButton.Name = "RemoveButton"

    Me.RemoveButton.Size = New System.Drawing.Size(115, 23)

    Me.RemoveButton.TabIndex = 4

    Me.RemoveButton.Text = "Remove Path"

    Me.RemoveButton.UseVisualStyleBackColor = True

    '

    'ExecuteButton

    '

    Me.ExecuteButton.Location = New System.Drawing.Point(12, 274)

    Me.ExecuteButton.Name = "ExecuteButton"

    Me.ExecuteButton.Size = New System.Drawing.Size(75, 23)

    Me.ExecuteButton.TabIndex = 5

    Me.ExecuteButton.Text = "Execute"

    Me.ExecuteButton.UseVisualStyleBackColor = True

    '

    'SubFoldersCheckBox

    '

    Me.SubFoldersCheckBox.AutoSize = True

    Me.SubFoldersCheckBox.Location = New System.Drawing.Point(13, 43)

    Me.SubFoldersCheckBox.Name = "SubFoldersCheckBox"

    Me.SubFoldersCheckBox.Size = New System.Drawing.Size(114, 17)

    Me.SubFoldersCheckBox.TabIndex = 6

    Me.SubFoldersCheckBox.Text = "Include Subfolders"

    Me.SubFoldersCheckBox.UseVisualStyleBackColor = True

    '

    'Label1

    '

    Me.Label1.AutoSize = True

    Me.Label1.Location = New System.Drawing.Point(133, 44)

    Me.Label1.Name = "Label1"

    Me.Label1.Size = New System.Drawing.Size(78, 13)

    Me.Label1.TabIndex = 7

    Me.Label1.Text = "Search Pattern"

    '

    'PatternTextBox

    '

    Me.PatternTextBox.Location = New System.Drawing.Point(217, 41)

    Me.PatternTextBox.Name = "PatternTextBox"

    Me.PatternTextBox.Size = New System.Drawing.Size(100, 20)

    Me.PatternTextBox.TabIndex = 8

    Me.PatternTextBox.Text = "*.*"

    Me.PatternTextBox.TextAlign = System.Windows.Forms.HorizontalAlignment.Center

    '

    'Form1

    '

    Me.AutoScaleDimensions = New System.Drawing.SizeF(6.0!, 13.0!)

    Me.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font

    Me.ClientSize = New System.Drawing.Size(399, 312)

    Me.Controls.Add(Me.PatternTextBox)

    Me.Controls.Add(Me.Label1)

    Me.Controls.Add(Me.SubFoldersCheckBox)

    Me.Controls.Add(Me.ExecuteButton)

    Me.Controls.Add(Me.RemoveButton)

    Me.Controls.Add(Me.AddButton)

    Me.Controls.Add(Me.BrowseButton)

    Me.Controls.Add(Me.NewPathTextBox)

    Me.Controls.Add(Me.FoldersListBox)

    Me.Name = "Form1"

    Me.Text = "Form1"

    CType(Me.BindingSource1, System.ComponentModel.ISupportInitialize).EndInit()

    Me.ResumeLayout(False)

    Me.PerformLayout()

    End Sub

    Friend WithEvents FoldersListBox As System.Windows.Forms.ListBox

    Friend WithEvents NewPathTextBox As System.Windows.Forms.TextBox

    Friend WithEvents BrowseButton As System.Windows.Forms.Button

    Friend WithEvents FolderBrowserDialog1 As System.Windows.Forms.FolderBrowserDialog

    Friend WithEvents AddButton As System.Windows.Forms.Button

    Friend WithEvents RemoveButton As System.Windows.Forms.Button

    Friend WithEvents ExecuteButton As System.Windows.Forms.Button

    Friend WithEvents SubFoldersCheckBox As System.Windows.Forms.CheckBox

    Friend WithEvents Label1 As System.Windows.Forms.Label

    Friend WithEvents PatternTextBox As System.Windows.Forms.TextBox

    Friend WithEvents BindingSource1 As System.Windows.Forms.BindingSource

    End Class

    Form1.vb – This is the code that does the actual work

    Public Class Form1

    'Create a collection to hold each folder entry item

    Private myFolders As List(Of FolderEntry)

    'Declare a variable to hold the save file location

    Private mySaveFile As String

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

    'Build the save file location

    mySaveFile = System.IO.Path.Combine(My.Application.Info.DirectoryPath, "folderlist.bin")

    'If the save file exists, load it

    If System.IO.File.Exists(Me.mySaveFile) Then

    'Create a binary serilizer

    Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

    'Create a file stream

    Dim fs As New System.IO.FileStream(Me.mySaveFile, IO.FileMode.Open)

    'Deserialize the binary file into a List(of FolderEntry) object

    Me.myFolders = CType(bf.Deserialize(fs), List(Of FolderEntry))

    'Close the file stream

    fs.Close()

    Else

    'If there is no save file, create a new List(Of FolderEntry) object

    Me.myFolders = New List(Of FolderEntry)

    End If

    'Setup the binding for the listbox

    Me.BindingSource1.DataSource = Me.myFolders

    Me.FoldersListBox.DisplayMember = "Path"

    Me.FoldersListBox.DataSource = Me.BindingSource1

    End Sub

    Private Sub Form1_FormClosing(ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosingEventArgs) Handles Me.FormClosing

    'When the form closes, save the List(Of FolderEntry) object

    Dim bf As New System.Runtime.Serialization.Formatters.Binary.BinaryFormatter

    Dim fs As New System.IO.FileStream(Me.mySaveFile, IO.FileMode.Create)

    bf.Serialize(fs, Me.myFolders)

    fs.Close()

    End Sub

    Private Sub BrowseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles BrowseButton.Click

    'Allow the user to browse to a folder

    If Me.FolderBrowserDialog1.ShowDialog = Windows.Forms.DialogResult.OK Then

    Me.NewPathTextBox.Text = Me.FolderBrowserDialog1.SelectedPath

    End If

    End Sub

    Private Sub AddButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles AddButton.Click

    'Add a new folder entry to the list

    Me.BindingSource1.Add(New FolderEntry(Me.NewPathTextBox.Text, Me.SubFoldersCheckBox.Checked, Me.PatternTextBox.Text))

    End Sub

    Private Sub RemoveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles RemoveButton.Click

    'Remove the selected folder entry from the list

    If Me.FoldersListBox.SelectedIndex > -1 Then

    Me.BindingSource1.Remove(Me.FoldersListBox.SelectedItem)

    End If

    End Sub

    Private Sub ExecuteButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles ExecuteButton.Click

    'Check each folder in the list

    For Each fe As FolderEntry In Me.myFolders

    Me.DeleteOldFiles(fe.Path, fe.IncludeSubFolders, fe.SearchPattern)

    Next

    MessageBox.Show("File check complete.", "Done", MessageBoxButtons.OK, MessageBoxIcon.Information)

    End Sub

    'Create a sub to delete the old files

    'Tell the routine the path to delete from, whether to check sub directories, and what file names and/or types to delete

    Private Sub DeleteOldFiles(ByVal path As String, ByVal includeSubDir As Boolean, Optional ByVal fileFilter As String = "*.*")

    'Check if the path supplied exists

    If System.IO.Directory.Exists(path) Then

    'Get the search option based on the parameter

    Dim opt As System.IO.SearchOption

    If includeSubDir Then

    opt = IO.SearchOption.AllDirectories

    Else

    opt = IO.SearchOption.TopDirectoryOnly

    End If

    'Get the list of files

    Dim files() As String = System.IO.Directory.GetFiles(path, fileFilter, opt)

    'Loop through each file name in the list

    For Each f As String In files

    'Get the creation time of the file

    Dim created As Date = System.IO.File.GetCreationTime(f)

    'If it was created more than 10 days ago...

    If Now.Subtract(created).TotalDays > 10 Then

    'Delete the file

    System.IO.File.Delete(f)

    End If

    Next

    Else

    'If the path was invalid throw an exception that says so

    Throw New ArgumentException("The path specified does not exist.")

    End If

    End Sub

    End Class

    'Create a simple class to hold each folder entry

    'Mark it Serializable for easy saving

    <Serializable()> _

    Public Class FolderEntry

    Private myPath As String

    Private mySubFolders As Boolean

    Private myPattern As String

    Public Sub New()

    MyBase.New()

    End Sub

    Public Sub New(ByVal path As String, ByVal subFolders As Boolean, Optional ByVal pattern As String = "*.*")

    MyBase.New()

    Me.myPath = path

    Me.mySubFolders = subFolders

    Me.myPattern = pattern

    End Sub

    Public Property Path() As String

    Get

    Return Me.myPath

    End Get

    Set(ByVal value As String)

    Me.myPath = value

    End Set

    End Property

    Public Property IncludeSubFolders() As Boolean

    Get

    Return Me.mySubFolders

    End Get

    Set(ByVal value As Boolean)

    Me.mySubFolders = value

    End Set

    End Property

    Public Property SearchPattern() As String

    Get

    Return Me.myPattern

    End Get

    Set(ByVal value As String)

    Me.myPattern = value

    End Set

    End Property

    End Class

    That should give you something to work with/learn from.

    Hope it helps! Good luck!!



  • brian_tsim

    The path cannot be more than 1 directory unfortunately I believe. if you specify "C:\" it will get a list of folders in C:\ (the root directory of your harddrive).

    You can however specify a search pattern The search pattern will give you back the folders which contain the specified search "expression"

    so logically/in theory if you did this:

    Dim theFolders() as String = System.IO.Directories.GetDirectories("C:\", "temp*")

    it should return you back all folders which start with "temp", since we specified "temp" and an astrix to indicate that the folders must start with temp and have anything else after it

    Also note, it should be "as String" and not "as new String" - which I will correct in my original reply :-)



  • Mike Wilson

    Thank you for your reply. I understand the array portion, and the general use of the system.IO, and I even understand how you are traversing each directory with the "for each currentfolder" statement, but I am a little confused with :

    Dim theFolders() as new String = System.IO.Directories.GetDirectories("Path")


    can path = more than one directory.... e.g.

    Dim theFolders() as new String = System.IO.Directories.GetDirectories("C:\temp2, C:\temp3")



    Thanks again for your help!

    -A noob

  • Part Time Australian

    Here's some example code. You create a subroutine that does the actual deletion and call that sub for each folder that you want to check. This way the code does not change no matter how many folders need to be checked. You just keep calling the same routine and passing in the folder path. This example also takes parameters for the type of files to check based on name and/or extension (e.g. *.* for all files) and it takes a True/False that specifies whether to search each sub directory in the given path.

    Here's the example:

    'Create a sub to delete the old files

    'Tell the routine the path to delete from, whether to check sub directories, and what file names and/or types to delete

    Private Sub DeleteOldFiles(ByVal path As String, ByVal includeSubDir As Boolean, Optional ByVal fileFilter As String = "*.*")

    'Check if the path supplied exists

    If System.IO.Directory.Exists(path) Then

    'Get the search option based on the parameter

    Dim opt As System.IO.SearchOption

    If includeSubDir Then

    opt = IO.SearchOption.AllDirectories

    Else

    opt = IO.SearchOption.TopDirectoryOnly

    End If

    'Get the list of files

    Dim files() As String = System.IO.Directory.GetFiles(path, fileFilter, opt)

    'Loop through each file name in the list

    For Each f As String In files

    'Get the creation time of the file

    Dim created As Date = System.IO.File.GetCreationTime(f)

    'If it was created more than 10 days ago...

    If Now.Subtract(created).TotalDays > 10 Then

    'Delete the file

    System.IO.File.Delete(f)

    End If

    Next

    Else

    'If the path was invalid throw an exception that says so

    Throw New ArgumentException("The path specified does not exist.")

    End If

    End Sub

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

    'Delete all old files in C:\temp1 and in all sub directories in C:\temp1

    Me.DeleteOldFiles("c:\temp1", True)

    'Delete all old files in C:\temp2 but not in any sub directories in C:\temp2

    Me.DeleteOldFiles("c:\temp2", False)

    'Delete only old text files in C:\temp3 and in all sub directories

    Me.DeleteOldFiles("c:\temp3", True, "*.txt")

    End Sub

    The example code for Button1 just shows three calls to the DeleteOldFiles() method using various parameter options.

    Now, if you wanted to, you could create a list of folder paths and loop through the list calling the DeleteOldFiles() method for each entry. In this way the user could specify which folders to check.

    HTH!



  • UnKnown Nick

    This is awesome. Thank you soooooooo much for your help. Just wondering what you thought was the best way to pass the diferent folder names to the DeleteOldFiles() func I was thinking about making an array, and putting the different folders in hte array, and calling it that way. Seems a little complicated(my way that is :) ), anyway, thank you for your example!!! You the man.
  • Iterating through a list of folders