Getfile with multiple extension filter and order by file name - vb.net

i am working on vb.net desktop application.now i need that files coming from directory is in with extension .txt and .sql and also need that files coming in order by folder name. in need both together how to do it?
Try
Dim s As String = Txtfolder.Text
Dim files As List(Of String) = New List(Of String)()
Try
For Each f As String In Directory.GetFiles(s, "*.*").Where(Function(f1) f1.EndsWith(".sql") OrElse f1.EndsWith(".txt")).OrderBy(Function(f) f.LastWriteTime).First()
files.Add(f)
Next
For Each d As String In Directory.GetDirectories(s)
files.AddRange(DirSearch(d))
Next
Catch excpt As System.Exception
MessageBox.Show(excpt.Message)
End Try
Private Function DirSearch(ByVal sDir As String) As List(Of String)
Dim files As List(Of String) = New List(Of String)()
Try
For Each f As String In Directory.GetFiles(sDir, "*.*").Where(Function(f1) f1.EndsWith(".sql") OrElse f1.EndsWith(".txt"))
files.Add(f)
Next
For Each d As String In Directory.GetDirectories(sDir)
files.AddRange(DirSearch(d))
Next
Catch excpt As System.Exception
MessageBox.Show(excpt.Message)
End Try
Return files
End Function

Here is an example of option 1 from my comment, i.e. get all file paths and filter yourself:
Dim folderPath = "folder path here"
Dim filePaths = Directory.GetFiles(folderPath).
Where(Function(s) {".txt", ".sql"}.Contains(Path.GetExtension(s))).
OrderBy(Function(s) Path.GetFileName(s)).
ToArray()
Here's an example of option 2, i.e. get paths by extension and combine:
Dim folderPath = "folder path here"
Dim filePaths = Directory.GetFiles(folderPath, "*.txt").
Concat(Directory.GetFiles(folderPath, "*.sql")).
OrderBy(Function(s) Path.GetFileName(s)).
ToArray()

An alternative method, which allows searching for multiple directories and filtering the results using multiple search patterns.
It returns an ordered List(Of String):
Private Function DirSearch(ByVal sDirList As String(), SearchPatter As String()) As List(Of String)
Return sDirList.SelectMany(
Function(dir) SearchPatter.SelectMany(
Function(filter)
Return Directory.GetFiles(dir, filter, SearchOption.AllDirectories)
End Function).OrderBy(Function(xDir) xDir)).ToList()
End Function
You can pass the method a list of paths and a list of extensions:
Dim SearchPaths As String() = New String() {"[Directory1]", "[Directory2]"}
Dim ItemSearchPattern As String() = New String() {"*.txt", "*.sql", "*.jpg"}
Dim DirListing As List(Of String) = DirSearch(SearchPaths, ItemSearchPattern)
Extract the content of a sigle directory with:
Dim FilesInDir As List(Of String) = DirListing.
Where(Function(entry) entry.ToUpper().
Contains("[DirectoryName]".ToUpper())).ToList()
This is a case insensitive filter. Remove (ToUpper()) for a case sensitive one.

Related

Two List(Of String), when I add a value to one it gets added to the other

I'm getting the folders in two different directories and putting their names into two listviews, but if one folder name exist in only one directory I would like to enter nothing into the other list and vice versa, unless the folder name is in both, then I just want the name in both lists.
Here is the code I am using:
Private folders As New List(Of String), oFolders As New List(Of String), AllFoldrs As New List(Of DirectoryInfo), CurFdr As DirectoryInfo
Private Sub Get_LVItems()
folders.Clear() : oFolders.Clear() : CurLV.Items.Clear() : AllFoldrs.Clear() 'Empty folders List and CurrentLV items
Dim LV As ListView = CurLV, oLV As ListView = OtherLv
Dim Pth As String = CurTV.SelectedNode.Name, oPth As String = ""
Dim Dinfo As New DirectoryInfo(Pth), oDinfo As DirectoryInfo = Nothing
Dim TmpFoldrs As New List(Of DirectoryInfo), oTmpFoldrs As New List(Of DirectoryInfo)
If Not IsNothing(OtherTV.SelectedNode) Then
End If
If TVs_Syncd Then
oPth = OtherTV.SelectedNode.Name : oDinfo = New DirectoryInfo(oPth)
TmpFoldrs.AddRange(Dinfo.GetDirectories) : oTmpFoldrs.AddRange(oDinfo.GetDirectories)
AllFoldrs.AddRange(Dinfo.GetDirectories) : AllFoldrs.AddRange(oDinfo.GetDirectories)
AllFoldrs.Sort(AddressOf SrtAllFdrs)
Do While AllFoldrs.Count > 0
CurFdr = AllFoldrs(0)
Dim Found_fdr As DirectoryInfo = Nothing, oFound_fdr As DirectoryInfo = Nothing
For Each fdr As DirectoryInfo In TmpFoldrs
If fdr.Name = CurFdr.Name Then Found_fdr = fdr : Exit For
Next
If IsNothing(Found_fdr) Then folders.Add(Nothing) Else folders.Add(Found_fdr.FullName)
For Each ofdr As DirectoryInfo In oTmpFoldrs
If ofdr.Name = CurFdr.Name Then oFound_fdr = ofdr : Exit For
Next
If IsNothing(oFound_fdr) Then oFolders.Add(Nothing) Else oFolders.Add(oFound_fdr.FullName)
AllFoldrs.RemoveAll(AddressOf RemDirs)'After adding a folder to both collections (folders & oFolders) all instances of that folder get removed from AllFolders
Loop
LoadListView(oLV)
folders.Clear()
folders = oFolders
LoadListView(LV)
Else
folders.AddRange(Directory.GetDirectories(Pth))
LoadListView(LV)
End If
End Sub
two functions:
for removing all instances of the folder name just processed and
the sort function for sorting AllFoldrs after adding all the folder names to it:
Public Function RemDirs(dir As DirectoryInfo) As Boolean
Return dir.Name = CurFdr.Name
End Function
Public Function SrtAllFdrs(ByVal X As DirectoryInfo, ByVal Y As DirectoryInfo) As Integer
Return X.Name.CompareTo(Y.Name)
End Function
I add both directories folders to AllFolders and each directories folders to their own Tmp List.
In the first For Each loop, I see if the current folder name exists in tmp list, if it does I put the value into Found_fdr then when I add it to the list(Of String) I am using to fill list A, it gets added to the other list(Of String) at the same time. I's baffling me!
This is much more to the point than my last question that got no answers, which really didn't surprise me. Anyone? Please...

Searching Multiple strings with 1st criteria, then searching those returned values with a different criteria and so on

so..
I have a txt file with hundreds of sentences or strings.
I also have 4 comboboxes with options that a user can select from and
each combobox is part of a different selection criteria. They may or may not use all the comboboxes.
When a user selects an option from any combobox I use a For..Next statement to run through the txt file and pick out all the strings that contain or match whatever the user selected. It then displays those strings for the user to see, so that if they wanted to they could further narrow down the search from that point by using the 3 remaining comboboxes making it easier to find what they want.
I can achieve this by using lots of IF statements within the for loop but is that the only way?
No, there are other ways. You can leverage LINQ to get rid of some of those if statements:
Private _lstLinesInFile As List(Of String) = New List(Of String)
Private Function AddClause(ByVal qryTarget As IEnumerable(Of String), ByVal strToken As String) As IEnumerable(Of String)
If Not String.IsNullOrWhiteSpace(strToken) Then
qryTarget = qryTarget.Where(Function(ByVal strLine As String) strLine.Contains(strToken))
End If
Return qryTarget
End Function
Public Sub YourEventHandler()
'Start Mock
Dim strComboBox1Value As String = "Test"
Dim strComboBox2Value As String = "Stack"
Dim strComboBox3Value As String = String.Empty
Dim strComboBox4Value As String = Nothing
'End Mock
If _lstLinesInFile.Count = 0 Then
'Only load from the file once.
_lstLinesInFile = IO.File.ReadAllLines("C:\Temp\Test.txt").ToList()
End If
Dim qryTarget As IEnumerable(Of String) = (From strTarget In _lstLinesInFile)
'Assumes you don't have to match tokens that are split by line breaks.
qryTarget = AddClause(qryTarget, strComboBox1Value)
qryTarget = AddClause(qryTarget, strComboBox2Value)
qryTarget = AddClause(qryTarget, strComboBox3Value)
qryTarget = AddClause(qryTarget, strComboBox4Value)
Dim lstResults As List(Of String) = qryTarget.ToList()
End Sub
Keep in mind this is case sensitive so you may want to throw in some .ToLower() calls in there:
qryTarget = qryTarget.Where(Function(ByVal strLine As String) strLine.ToLower().Contains(strToken.ToLower()))
I think a compound If statement is the simplest:
Dim strLines() As String = IO.File.ReadAllText(strFilename).Split(vbCrLf)
Dim strSearchTerm1 As String = "Foo"
Dim strSearchTerm2 As String = "Bar"
Dim strSearchTerm3 As String = "Two"
Dim strSearchTerm4 As String = ""
Dim lstOutput As New List(Of String)
For Each s As String In strLines
If s.Contains(strSearchTerm1) AndAlso
s.Contains(strSearchTerm2) AndAlso
s.Contains(strSearchTerm3) AndAlso
s.Contains(strSearchTerm4) Then
lstOutput.Add(s)
End If
Next

List all folders that are in any 3rd subdirectory from current

I would need to make an array list, displaying all folders that are in the 3rd subfolder from the current one.
Folder1/sub1folder/sub2folder/sub3folder
It has to be recursive. what I need is an array of strings that contains all the strings like above.
I do know how to look recursively into folders, but I do not know how to limit the search to the 3rd subfolder.
Thanks!
Here's my stab at it. I tested it and it works for me:
Dim resultList as List(Of String) = DirectorySearch(baseDirectoryPath, 0)
Function DirectorySearch(directoryPath As String, level As Integer) As List(Of String)
level += 1
Dim directories As String() = IO.Directory.GetDirectories(directoryPath)
Dim resultList As New List(Of String)
If level = 3 Then
For Each subDirectoryPath In directories
Dim result As String = GetFinalResult(subDirectoryPath)
resultList.Add(result)
Next
Else
For Each subDirectoryPath In directories
Dim partialResultList As List(Of String) = DirectorySearch(subDirectoryPath, level)
resultList.AddRange(partialResultList)
Next
End If
Return resultList
End Function
Private Function GetFinalResult(directoryPath As String) As String
Dim directoryInfo As New IO.DirectoryInfo(directoryPath)
Return String.Format("{0}/{1}/{2}/{3}",
directoryInfo.Parent.Parent.Parent.Name,
directoryInfo.Parent.Parent.Name,
directoryInfo.Parent.Name,
directoryInfo.Name)
End Function
If you had a recursive function which began at the current folder:
Public Function recurse(Optional depth As Integer = 0) As String()
Dim folderList As String()
If (depth < 3) Then
depth += 1
folderList = recurse(depth)
Else
'Do third subfolder analysis and set the output to folderList
Return folderList
End If
End Sub

vb.net get filename list from wildcard

I have string say "c:\debug\ *.txt"
In Debug folder there are severeal .txt files , say test1.txt test2.txt test3.txt .
How can I get from this string c:\debug\ *.txt an array of wildcard files?
a(0)=c:\debug\test1.txt
a(1)=c:\debug\test2.txt
a(2)=c:\debug\test3.txt
It is also possible that the string would be something like "C:\logs\12*\ *.log"
a(0)=C:\logs\120114\01.log
a(0)=C:\logs\120114\02.log
a(0)=C:\logs\120114\03.log
etc.
Anyone have any ideas on this?
I use the following code:
Dim Path As String = "C:\debug"
Dim Dir As New DirectoryInfo(Path)
Dim q = (From x In Dir.GetFiles("*.txt", SearchOption.AllDirectories) Select x.FullName).ToArray
You might need to
Import System.IO
Import System.Linq
Basically your key for the requirement is SearchOption.AllDirectories which iterates through sub directories as well.
This should do it for you. It'll handle wildcards in directory part and filename part
Private Function GetFiles(ByVal Path As String) As List(Of String)
Dim drivePart As String, dirPart As String, filePart As String
drivePart = Path.Substring(0, Path.IndexOf("\") + 1)
dirPart = Path.Substring(Path.IndexOf("\") + 1, Path.LastIndexOf("\") - Path.IndexOf("\") - 1)
filePart = Path.Substring(Path.LastIndexOf("\") + 1)
Dim directories As New List(Of String)
Dim files As New List(Of String)
'' Walk directory tree finding matches
'' This should handle wildcards in any part of the path
Dim currentIndex As Integer = 0
Dim directoryMatch As String() = dirPart.Split("\")
For Each directory As String In directoryMatch
WalkDirectories(drivePart, directories, directoryMatch, currentIndex)
currentIndex += 1
Next
For Each directory As String In directories
files.AddRange(System.IO.Directory.GetFiles(directory, filePart))
Next
Return files
End Function
Private Sub WalkDirectories(ByVal dirPart As String, ByVal directories As List(Of String), ByVal directoryMatch As String(), ByVal currentIndex As Integer)
If currentIndex = directoryMatch.Length Then Return
For Each d As String In System.IO.Directory.GetDirectories(dirPart, directoryMatch(currentIndex))
directories.Add(d)
WalkDirectories(System.IO.Path.Combine(dirPart, d), directories, directoryMatch, currentIndex + 1)
Next
End Sub
Edit: just noticed that it wont handle UNC paths but it should be pretty easy to modify for that if you need to
Editted again to handle multiple directory levels and wildcards at multiple levels (eg C:\debug\12*\log1*\errors*.txt
Use the GetFiles from My.Computer.System and the ReadOnlyCollection(of String) from the system.collections.objectModel import and a searchoption as desired (top or all)
sPath = "C:\debug" ' your desired path
sFile1 = "t*.txt" ' your desired search pattern with * wildcard
sFile2 = "test?.txt" ' your desired search pattern with ? wildcard
dim lstFiles as system.collections.ObjectModel.ReadOnlyCollection(of String) = My.Computer.Filesystem.GetFiles(sPath, FileIO.SearchOption.SearchTopLevelOnly, sFile1)
'lstfiles contains all the files that match your selection
'if you really need an array you can convert the list to array here
dim i as integer = 0
for each sFile as string in lstfiles
a(i)=sfile
i+=1
next
You could use the 'Like' keyword:
' For your example, call this function with root = "C:\logs" and wild = "12*\*.log"
Friend Function GetMyFiles(root As String, wild As String, Optional allowsub As Boolean = True) As List(Of String)
Dim a As New List(Of String), pattern As String
' ensure root ends with a \
If Not root.EndsWith("\") Then root &= "\"
' the extra * allows for subdirectories in between, if required
pattern = root & If(allowsub, "*", "") & wild
For Each f As String In My.Computer.FileSystem.GetFiles(root, FileIO.SearchOption.SearchAllSubDirectories)
If f Like pattern Then a.Add(f)
Next
Return a
End Function
Of course, if you hit a protected system directory, it'll fail.
This function is just to demonstrate the 'Like' keyword.
It will work if 'root' isn't a drive root (e.g. C:).
Done properly, a separate function would collect directories first, each tested for access permissions in a Try/Catch block. Here's how that looks:
Friend Function GetAllAccessibleDirs(ByRef Dir As String, Optional inclDir As Boolean = True, Optional Sort As Boolean = False) As List(Of String)
Dim D As New List(Of String), Q As New Queue(Of String), dummy As DirectoryInfo, s As String
If inclDir Then D.Add(Dir)
Q.Enqueue(Dir)
While Q.Count
For Each s In GetTopLevelDirs(Q.Dequeue)
Try
dummy = My.Computer.FileSystem.GetDirectoryInfo(s)
D.Add(s)
Q.Enqueue(s)
Catch
' Inaccessible folder
End Try
Next
End While
If Sort AndAlso D.Count Then D.Sort()
Return D
End Function
Friend Function GetTopLevelDirs(ByRef dir As String) As List(Of String)
Try
Return My.Computer.FileSystem.GetDirectories(dir, FileIO.SearchOption.SearchTopLevelOnly).ToList
Catch
Return New List(Of String)
End Try
End Function

Searching By File Extensions VB.NET [duplicate]

This question already has answers here:
What is a NullReferenceException, and how do I fix it?
(27 answers)
Closed 5 years ago.
Hi all i have been trying to search a specified directory and all sub directories for all files that have the specified file extension. However the inbuilt command is useless as it errors up and dies if you dont have access to a directory. So here's what i have at the moment:
Private Function dirSearch(ByVal path As String, Optional ByVal searchpattern As String = ".exe") As String()
Dim di As New DirectoryInfo(path)
Dim fi As FileInfo
Dim filelist() As String
Dim i As Integer = 0
For Each fi In di.GetFiles
If System.IO.Path.GetExtension(fi.FullName).ToLower = searchpattern Then
filelist(i) = fi.FullName
i += 1
End If
Next
Return filelist
End Function
However i get an "System.NullReferenceException: Object reference not set to an instance of an object." when i try to access the data stored inside the filelist string array.
Any idea's on what im doing wrong?
You didn't instantiate the Dim filelist() As String array. Try di.GetFiles(searchPattern)
Dim files() as FileInfo = di.GetFiles(searchPattern)
Use static method Directory.GetFiles that returns an array string
Dim files = Directory.GetFiles(Path,searchPattern,searchOption)
Demo:
Dim files() As String
files = Directory.GetFiles(path, "*.exe", SearchOption.TopDirectoryOnly)
For Each FileName As String In files
Console.WriteLine(FileName)
Next
Recursive directory traversal:
Sub Main()
Dim path = "c:\jam"
Dim fileList As New List(Of String)
GetAllAccessibleFiles(path, fileList)
'Convert List<T> to string array if you want
Dim files As String() = fileList.ToArray
For Each s As String In fileList
Console.WriteLine(s)
Next
End Sub
Sub GetAllAccessibleFiles(path As String, filelist As List(Of String))
For Each file As String In Directory.GetFiles(path, "*.*")
filelist.Add(file)
Next
For Each dir As String In Directory.GetDirectories(path)
Try
GetAllAccessibleFiles(dir, filelist)
Catch ex As Exception
End Try
Next
End Sub
Use System.IO.Directory.EnumerateFiles method and pass SearchOption.AllDirectories in to traverse the tree using a specific search pattern. Here is an example:
foreach (var e in Directory.EnumerateFiles("C:\\windows", "*.dll", SearchOption.AllDirectories))
{
Console.WriteLine(e);
}