none
search through subfolders until find one with specified name and then return value of next level folder name RRS feed

  • Question

  • i.e. if I supply C:\Backup then I want it to look through sub-folders until it finds one called Users and then return the child folder after it

    So if I have C:\Backup\Today\Users\Fred then it would stop at Users and return the value Fred

    If I had C:\Backup\Today\December\2016\Users\Donna then it would return Donna and stop looking

    I know how to look through directories but struggling with logic on how to search until it finds value e.g. "Users" and then just return next folder level and nothing else

    I can use below when I know Users is two levels deep, but what if it is deeper then I need to keep checking until it find "Users"

    Dim di As New DirectoryInfo(strFolderName) For Each subdi As DirectoryInfo In di.GetDirectories For Each subdi2 As DirectoryInfo In subdi.GetDirectories msgbox(subdi2.FullName)

    Next Next



    Darren Rose


    • Edited by wingers Saturday, February 25, 2017 5:00 PM
    Saturday, February 25, 2017 5:00 PM

Answers

  • Will give it a try shortly thanks Frank - for moment having issue with PathFindAndReplace in backup tool - will post about that on the other thread....

    Darren Rose

    To get to specifically what you want, you might use this:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Imports System.IO
    
    Public Class Form1
        Private Sub Form1_Load(sender As System.Object, _
                               e As System.EventArgs) _
                               Handles MyBase.Load
    
            Dim mainDI As New DirectoryInfo("X:\Music Files")
            Const dirNameToSearchFor As String = "chicago"
    
            Dim fiList As New List(Of FileInfo)
    
            If mainDI.Exists Then
                Dim infos As FileSystemInfo() = mainDI.GetFileSystemInfos("*", SearchOption.AllDirectories)
    
                If infos IsNot Nothing AndAlso infos.Count > 0 Then
                    Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _
                        From fsi As FileSystemInfo In infos _
                            Where TypeOf fsi Is DirectoryInfo AndAlso _
                                         fsi.Name.ToLower.Replace(" "c, "") = dirNameToSearchFor.ToLower.Replace(" "c, "")
    
                    If diQry IsNot Nothing Then
                        Dim di As DirectoryInfo = _
                            (DirectCast(diQry.First, DirectoryInfo)).EnumerateDirectories.FirstOrDefault
    
                        If di IsNot Nothing Then
                            MessageBox.Show(di.FullName, "Result")
                        End If
    
                        Stop
                    End If
                End If
            End If
    
            Stop
    
        End Sub
    End Class

    But do note that I'll caution: "Define what is the first". In the foregoing it's just the first one that the OS came to.


    "One who has no vices also has no virtues..."

    • Marked as answer by wingers Sunday, February 26, 2017 4:21 PM
    Saturday, February 25, 2017 8:31 PM
  • i.e. if I supply C:\Backup then I want it to look through sub-folders until it finds one called Users and then return the child folder after it

    So if I have C:\Backup\Today\Users\Fred then it would stop at Users and return the value Fred

    If I had C:\Backup\Today\December\2016\Users\Donna then it would return Donna and stop looking

    I know how to look through directories but struggling with logic on how to search until it finds value e.g. "Users" and then just return next folder level and nothing else

    I can use below when I know Users is two levels deep, but what if it is deeper then I need to keep checking until it find "Users"

    Dim di As New DirectoryInfo(strFolderName) For Each subdi As DirectoryInfo In di.GetDirectories For Each subdi2 As DirectoryInfo In subdi.GetDirectories msgbox(subdi2.FullName)

    Next Next



    Darren Rose


    This is something I threw together very quickly. It does not check for permissions, you should use something like John Wein's safe folder finder if necessary.

    Public Class Form1
        Private Function GetTheFolder(RootPath As String) As String
            Dim Folders As New List(Of String)
            Folders.AddRange(My.Computer.FileSystem.GetDirectories(RootPath, FileIO.SearchOption.SearchTopLevelOnly))
            If Folders.Count > 0 Then
                Return New IO.DirectoryInfo(Folders(0)).Name
            Else
                Return "Nothing was Found under the requested Folder"
            End If
        End Function
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    
            Dim FolderToFind As String = "Users"
            Dim StartPoint As String = "H:\VirtualStore\Program Files"
    
            For Each FName As String In My.Computer.FileSystem.GetDirectories(StartPoint, FileIO.SearchOption.SearchAllSubDirectories)
                If FName.EndsWith(FolderToFind) Then
                    TextBox1.Text = "A folder named '" & GetTheFolder(FName) & "' was found here - " & FName
                    Exit Sub
                End If
            Next
            TextBox1.Text = "No Folder named " & FolderToFind & " was found"
        End Sub
    End Class

    • Marked as answer by wingers Sunday, February 26, 2017 4:22 PM
    Sunday, February 26, 2017 1:58 AM

All replies

  • Darren,

    As a starting place - since I don't have your data - try this which starts at c:\:

    ** If you can hone it down closer than the entire drive then please do for the sake of speed **

            Const drive As String = "c:\"
    
            Dim di As New DirectoryInfo(drive)
    
            Dim result As IEnumerable(Of DirectoryInfo) = _
                di.EnumerateDirectories("*", SearchOption.TopDirectoryOnly)
    
            Dim rootLevelDirectories As New List(Of String)
    
            For Each info As DirectoryInfo In result
                If info.Attributes = 16 Then
                    rootLevelDirectories.Add(info.FullName)
                End If
            Next
    
            For Each directoryName As String In rootLevelDirectories
                Dim dir As New DirectoryInfo(directoryName)
    
                If dir.Exists Then
                    Dim infos As FileSystemInfo() = dir.GetFileSystemInfos("*", SearchOption.AllDirectories)
    
                    If infos IsNot Nothing AndAlso infos.Count > 0 Then
                        Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _
                            From fsi As FileSystemInfo In infos _
                                Where TypeOf fsi Is DirectoryInfo AndAlso fsi.Name.ToLower = "user"
    
                        If diQry.Count > 0 Then
                            Stop
                        End If
                    End If
                End If
            Next
    
            Stop

    Hopefully it will get the to the first stop, not the second one, but I have no way to test it.


    "One who has no vices also has no virtues..."

    Saturday, February 25, 2017 6:22 PM
  • Thanks Frank

    Yes I can narrow search down more than just the whole drive thankfully

    But with that code if I supply z: then it works but if I try to narrow it down say z:\backup it gets to second stop without finding users


    Darren Rose

    Saturday, February 25, 2017 6:31 PM
  • Thanks Frank

    Yes I can narrow search down more than just the whole drive thankfully

    But with that code if I supply z: then it works but if I try to narrow it down say z:\backup it gets to second stop without finding users


    Darren Rose

    I was writing that "off the cuff" and I think I might be a level too deep.

    I'll keep experimenting some but my theory is to get all FileInfo instances where the DirectoryInfo is what you want.

    Am I correct that there may me more than one "User" directory somewhere that you're looking for?


    "One who has no vices also has no virtues..."


    • Edited by Frank L. Smith Saturday, February 25, 2017 6:40 PM ...typo
    Saturday, February 25, 2017 6:39 PM
  • Okay, will play more with it later

    No should only be one User directory and even if more it would be the first one I needed and then it can stop looking as no need to search below it when found, only just to get the next folder name


    Darren Rose

    Saturday, February 25, 2017 6:47 PM
  • Darren,

    I used something that I could test. How about modify the following and let me know your results please?

    Option Strict On Option Explicit On Option Infer Off Imports System.IO Public Class Form1 Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load Dim mainDI As New DirectoryInfo("X:\Music Files") Const dirNameToSearchFor As String = "Canned Heat" Dim fiList As New List(Of FileInfo) If mainDI.Exists Then Dim infos As FileSystemInfo() = mainDI.GetFileSystemInfos("*", SearchOption.AllDirectories) If infos IsNot Nothing AndAlso infos.Count > 0 Then Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _ From fsi As FileSystemInfo In infos _ Where TypeOf fsi Is DirectoryInfo AndAlso _ fsi.Name.ToLower.Replace(" "c, "") = dirNameToSearchFor.ToLower.Replace(" "c, "") If diQry.Count > 0 Then For Each di As DirectoryInfo In diQry Dim files As IEnumerable(Of FileInfo) = _ di.EnumerateFiles("*", SearchOption.AllDirectories) If files IsNot Nothing Then fiList.AddRange(files) End If Next End If End If End If Stop End Sub End Class


    ...(yes, "Canned Heat" really was a band)


    "One who has no vices also has no virtues..."

    Saturday, February 25, 2017 6:58 PM
  • This would make a good "searcher" -- it's fairly fast.

    I changed the parameters (but not the method) in the following:

    Option Strict On Option Explicit On Option Infer Off Imports System.IO Public Class Form1 Private Sub Form1_Load(sender As System.Object, _ e As System.EventArgs) _ Handles MyBase.Load Dim mainDI As New DirectoryInfo("X:\Music Files") Const dirNameToSearchFor As String = "chicago" Dim fiList As New List(Of FileInfo) If mainDI.Exists Then Dim infos As FileSystemInfo() = mainDI.GetFileSystemInfos("*", SearchOption.AllDirectories) If infos IsNot Nothing AndAlso infos.Count > 0 Then Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _ From fsi As FileSystemInfo In infos _ Where TypeOf fsi Is DirectoryInfo AndAlso _ fsi.Name.ToLower.Replace(" "c, "") = dirNameToSearchFor.ToLower.Replace(" "c, "") If diQry.Count > 0 Then For Each di As DirectoryInfo In diQry Dim files As IEnumerable(Of FileInfo) = _ di.EnumerateFiles("*", SearchOption.AllDirectories) If files IsNot Nothing Then fiList.AddRange(files) End If Next End If End If End If Stop End Sub End Class


    The reason that I chose that main directory name is because it has a good many sub-directories (each with a few files):

    The result:

    Because the result is a collection of FileInfo objects, you have a lot of properties of use - including (per file) the file's directory as an instance of DirectoryInfo:

    I hope that gets you what you want?


    "One who has no vices also has no virtues..."

    Saturday, February 25, 2017 7:23 PM
  • Will give it a try shortly thanks Frank - for moment having issue with PathFindAndReplace in backup tool - will post about that on the other thread....

    Darren Rose

    Saturday, February 25, 2017 8:27 PM
  • Will give it a try shortly thanks Frank - for moment having issue with PathFindAndReplace in backup tool - will post about that on the other thread....

    Darren Rose

    To get to specifically what you want, you might use this:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Imports System.IO
    
    Public Class Form1
        Private Sub Form1_Load(sender As System.Object, _
                               e As System.EventArgs) _
                               Handles MyBase.Load
    
            Dim mainDI As New DirectoryInfo("X:\Music Files")
            Const dirNameToSearchFor As String = "chicago"
    
            Dim fiList As New List(Of FileInfo)
    
            If mainDI.Exists Then
                Dim infos As FileSystemInfo() = mainDI.GetFileSystemInfos("*", SearchOption.AllDirectories)
    
                If infos IsNot Nothing AndAlso infos.Count > 0 Then
                    Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _
                        From fsi As FileSystemInfo In infos _
                            Where TypeOf fsi Is DirectoryInfo AndAlso _
                                         fsi.Name.ToLower.Replace(" "c, "") = dirNameToSearchFor.ToLower.Replace(" "c, "")
    
                    If diQry IsNot Nothing Then
                        Dim di As DirectoryInfo = _
                            (DirectCast(diQry.First, DirectoryInfo)).EnumerateDirectories.FirstOrDefault
    
                        If di IsNot Nothing Then
                            MessageBox.Show(di.FullName, "Result")
                        End If
    
                        Stop
                    End If
                End If
            End If
    
            Stop
    
        End Sub
    End Class

    But do note that I'll caution: "Define what is the first". In the foregoing it's just the first one that the OS came to.


    "One who has no vices also has no virtues..."

    • Marked as answer by wingers Sunday, February 26, 2017 4:21 PM
    Saturday, February 25, 2017 8:31 PM
  • Will give it a try shortly thanks Frank - for moment having issue with PathFindAndReplace in backup tool - will post about that on the other thread....


    Darren Rose

    To get to specifically what you want, you might use this:

    Option Strict On
    Option Explicit On
    Option Infer Off
    
    Imports System.IO
    
    Public Class Form1
        Private Sub Form1_Load(sender As System.Object, _
                               e As System.EventArgs) _
                               Handles MyBase.Load
    
            Dim mainDI As New DirectoryInfo("X:\Music Files")
            Const dirNameToSearchFor As String = "chicago"
    
            Dim fiList As New List(Of FileInfo)
    
            If mainDI.Exists Then
                Dim infos As FileSystemInfo() = mainDI.GetFileSystemInfos("*", SearchOption.AllDirectories)
    
                If infos IsNot Nothing AndAlso infos.Count > 0 Then
                    Dim diQry As System.Collections.Generic.IEnumerable(Of FileSystemInfo) = _
                        From fsi As FileSystemInfo In infos _
                            Where TypeOf fsi Is DirectoryInfo AndAlso _
                                         fsi.Name.ToLower.Replace(" "c, "") = dirNameToSearchFor.ToLower.Replace(" "c, "")
    
                    If diQry IsNot Nothing Then
                        Dim di As DirectoryInfo = _
                            (DirectCast(diQry.First, DirectoryInfo)).EnumerateDirectories.FirstOrDefault
    
                        If di IsNot Nothing Then
                            MessageBox.Show(di.FullName, "Result")
                        End If
    
                        Stop
                    End If
                End If
            End If
    
            Stop
    
        End Sub
    End Class

    But do note that I'll caution: "Define what is the first". In the foregoing it's just the first one that the OS came to.


    "One who has no vices also has no virtues..."


    That works perfectly - thank you

    Darren Rose

    Saturday, February 25, 2017 8:39 PM


  • That works perfectly - thank you

    Darren Rose

    I meant to remove "Dim fiList..." because it's not being used.

    *****

    The other one .. way way too long for me to navigate now but I got the e-mail:

    I never did like adding that part in but I do remember that it's all based on finding a part of the initial directory path -- otherwise there's nothing to find (and thus, nothing to replace).


    "One who has no vices also has no virtues..."

    Saturday, February 25, 2017 8:49 PM


  • That works perfectly - thank you

    Darren Rose

    I meant to remove "Dim fiList..." because it's not being used.

    *****

    The other one .. way way too long for me to navigate now but I got the e-mail:

    I never did like adding that part in but I do remember that it's all based on finding a part of the initial directory path -- otherwise there's nothing to find (and thus, nothing to replace).


    "One who has no vices also has no virtues..."

    Removed

    ***

    Yes I got that but what I am trying to replace clearly shows in the target path screenshot so can't understand why not working

    This is a key part of my app and if I can't get this working then all my work on the GUI and other code is all for nothing, so any ideas on troubleshooting or fixing it would be really very much appreciated :)


    Darren Rose

    Saturday, February 25, 2017 8:52 PM


  • ...(yes, "Canned Heat" really was a band)


    "One who has no vices also has no virtues..."

    Frank -

    I know it is off-topic but - My dental hygienist is Bob Hite's daughter. Sadly, he died way too soon, many years ago.

    Sunday, February 26, 2017 1:11 AM


  • ...(yes, "Canned Heat" really was a band)


    "One who has no vices also has no virtues..."

    Frank -

    I know it is off-topic but - My dental hygienist is Bob Hite's daughter. Sadly, he died way too soon, many years ago.


    Showing my age. ;-)

    "One who has no vices also has no virtues..."

    Sunday, February 26, 2017 1:36 AM
  • i.e. if I supply C:\Backup then I want it to look through sub-folders until it finds one called Users and then return the child folder after it

    So if I have C:\Backup\Today\Users\Fred then it would stop at Users and return the value Fred

    If I had C:\Backup\Today\December\2016\Users\Donna then it would return Donna and stop looking

    I know how to look through directories but struggling with logic on how to search until it finds value e.g. "Users" and then just return next folder level and nothing else

    I can use below when I know Users is two levels deep, but what if it is deeper then I need to keep checking until it find "Users"

    Dim di As New DirectoryInfo(strFolderName) For Each subdi As DirectoryInfo In di.GetDirectories For Each subdi2 As DirectoryInfo In subdi.GetDirectories msgbox(subdi2.FullName)

    Next Next



    Darren Rose


    This is something I threw together very quickly. It does not check for permissions, you should use something like John Wein's safe folder finder if necessary.

    Public Class Form1
        Private Function GetTheFolder(RootPath As String) As String
            Dim Folders As New List(Of String)
            Folders.AddRange(My.Computer.FileSystem.GetDirectories(RootPath, FileIO.SearchOption.SearchTopLevelOnly))
            If Folders.Count > 0 Then
                Return New IO.DirectoryInfo(Folders(0)).Name
            Else
                Return "Nothing was Found under the requested Folder"
            End If
        End Function
        Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click
    
            Dim FolderToFind As String = "Users"
            Dim StartPoint As String = "H:\VirtualStore\Program Files"
    
            For Each FName As String In My.Computer.FileSystem.GetDirectories(StartPoint, FileIO.SearchOption.SearchAllSubDirectories)
                If FName.EndsWith(FolderToFind) Then
                    TextBox1.Text = "A folder named '" & GetTheFolder(FName) & "' was found here - " & FName
                    Exit Sub
                End If
            Next
            TextBox1.Text = "No Folder named " & FolderToFind & " was found"
        End Sub
    End Class

    • Marked as answer by wingers Sunday, February 26, 2017 4:22 PM
    Sunday, February 26, 2017 1:58 AM
  • Thanks Devon - that also works well for me

    Darren Rose

    Sunday, February 26, 2017 4:23 PM
  • Thanks Devon - that also works well for me

    Darren Rose

    Are you copying files individually, or combining all files into one large backup (compressed or raw) ?
    If combining, let me know and I can offer another method.

    Edit - Glad it helped
    Sunday, February 26, 2017 7:15 PM
  • Thanks Devon - that also works well for me


    Darren Rose

    Are you copying files individually, or combining all files into one large backup (compressed or raw) ?
    If combining, let me know and I can offer another method.

    Edit - Glad it helped

    I am copying files individually using the excellent FileCopier class Frank created for me to use = https://social.msdn.microsoft.com/Forums/vstudio/en-US/baec1c47-3dde-4667-a3d2-5ecbe1c3b59d/backup-tool-revisited?forum=vbgeneral

    Darren Rose

    Sunday, February 26, 2017 8:15 PM