Directory.GetFiles(strFolderPath) EXCLUDING Certain File Names VB.NET - vb.net

How would a do a Directory.GetFiles and exclude files called "abc" and "xyz"?
Basically I have a DIR where all the files exist and a particular group of files has to be sent to one department and the the "abc" and "xyz" file need to be sent to another?
At the moment I do this:
'Standard Documents
Dim strAttachments As List(Of String) = New List(Of String)
strAttachments.AddRange(Directory.GetFiles(GlobalVariables.strFolderPath))
I need the same functionality but excluding the files and then do a similar command as above to include the files to another address.
Cheers,,
James
UPDATE
Dim exclude = {"ATS_Declaration"}
Dim myFiles = From fn In Directory.EnumerateFiles(GlobalVariables.strFolderPath)
Where Not exclude.Contains(Path.GetFileNameWithoutExtension(fn), StringComparer.InvariantCultureIgnoreCase)
Dim strAttachments As List(Of String) = New List(Of String)(myFiles)

You can use LINQ and System.IO.Path.GetFileNameWithoutExtension:
Dim exclude = { "abc", "xyz" }
Dim myFiles = From fn in Directory.EnumerateFiles(GlobalVariables.strFolderPath)
Where Not exclude.Contains(Path.GetFileNameWithoutExtension(fn), StringComparer.InvariantCultureIgnorecase)
Dim strAttachments As List(Of String) = New List(Of String)(myFiles)
Note that i have used EnumerateFiles since that does not need to load all into memory first.

I couldn't get the answers here to exclude the file (not sure why Contains fails to match unless the file name is exactly the same as the exclusion string)
The answer below works wonderfully
Check this out: Exclude files from Directory.EnumerateFiles based on multiple criteria

Related

VB.net Apply function to items in a list

I have a list of string containing full file paths and I'd like to apply a function to each path in that list and get the result in the same or a new list.
Dim Remove As New List(Of String)
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Assemblies\045-0201.iam")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\212-D017.ipt")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\211-W01.iam")
Function FileName(spth As String) As String
'Returns filename with extension from full path
Return System.IO.Path.GetFileName(spth)
End Function
The end result I'd like is for the list Remove to contain the following. I know I could use a loop to do this but I've been learning about lambda expressions lately and feel there should be a simple solution to this.
{"045-0201.iam", "212-D017.ipt", "211-W01.iam"}
Try this
Dim Remove As New List(Of String)
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Assemblies\045-0201.iam")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\212-D017.ipt")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\211-W01.iam")
Remove = Remove.Select(Function(s)
Return IO.Path.GetFileName(s)
End Function).ToList
Calling Select and ToList on the existing List is most likely fine and what most people would do. It's worth being aware, though, that that will not modify the existing collection but rather return a new one. If you only have the one reference to that list then that's not a big deal but other references to the existing list will not see the change, e.g.
Dim fileNames As New List(Of String) From {"C:\Folder\File1.ext",
"C:\Folder\File2.ext",
"C:\Folder\File3.ext"}
Dim temp = fileNames
fileNames = fileNames.Select(Function(s) Path.GetFileName(s)).ToList()
For Each fileName In fileNames
Console.WriteLine(fileName)
Next
For Each fileName In temp
Console.WriteLine(fileName)
Next
If you run that then you'll see that the first loop displays just the files names but the second loop displays the full paths, because it still refers to the original list.
If that's a problem, there is another way to do this without an explicit loop:
Dim fileNames As New List(Of String) From {"C:\Folder\File1.ext",
"C:\Folder\File2.ext",
"C:\Folder\File3.ext"}
Dim temp = fileNames
Array.ForEach(Enumerable.Range(0, fileNames.Count).ToArray(),
Sub(i) fileNames(i) = Path.GetFileName(fileNames(i)))
For Each fileName In fileNames
Console.WriteLine(fileName)
Next
For Each fileName In temp
Console.WriteLine(fileName)
Next
If you run that then you'll see that both loops display just the file names because there's only one list.
That said, if the first code posed a problem because of multiple references to the list, I'd just use a loop.
I know you stated that you'd want something other than a loop, but there really is no needfor anything fancy here. By the way, writing Remove.Add sounds like a riddle.
Sub Main()
Dim Remove As New List(Of String)
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Assemblies\045-0201.iam")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\212-D017.ipt")
Remove.Add("C:\_Vault\Designs\Jobs\Customer\Job23\Parts\211-W01.iam")
Console.WriteLine("Before execution")
For Each s As String In Remove
Console.WriteLine(s)
Next
For i As Integer = 0 To Remove.Count - 1
Remove(i) = MyFunction(Remove(i))
Next
Console.WriteLine("After execution")
For Each s As String In Remove
Console.WriteLine(s)
Next
Console.ReadLine()
End Sub
Private Function MyFunction(path As String) As String
Return IO.Path.GetFileName(path)
End Function
This outputs:

How to search a folder with its subfolders and save the results to an array VB.NET

I am trying to execute a search on a folder and get an array of every result back. I found this code but it doesn't go into subfolders:
Dim Results As New List(Of String)
For Each strFileName As String In IO.Directory.GetFiles("pathToSearch")
If strFileName.Contains("searchTerm") Then
Results.Add(strFileName)
End If
Next
How can I do exactly this, but also look into the subfolders?
I'm not very knowledgeable about the search options in VB.NET yet, so I apologize in advance if this seems stupid. I have tried searching online but haven't found anything. I can't have a single string, it needs to be an array (this needs to be interpreted by the machine later in the program)
Thanks for any help
No recursion required. There is already an overload for this. You just need to call it with appropriate search option.
e.g. To list all txt files in the directory as well as the subdirectories you can do:
Dim foundFiles() As String = System.IO.Directory.GetFiles("path/to/dir", "*.txt", System.IO.SearchOption.AllDirectories)
In order to get the subfolders you might try some recursive function
Unless there's a file system search API with which I'm unfamiliar, this is going to involve a recursive method to perform the searching into sub-directories.
Helpfully, Microsoft even has a complete example of something very similar available. In VB it might look something like this (my VB is very rusty and this is free-hand code, by the way...):
Function FindFiles(ByVal dir As String, ByVal searchTerm As String) As List(Of String)
Dim Results As New List(Of String)
' search files in this directory
For Each strFileName As String In IO.Directory.GetFiles(dir)
If strFileName.Contains(searchTerm) Then
Results.Add(strFileName)
End If
Next
' recurse into child directories
For Each strDirectoryName As String In IO.Directory.GetDirectories(dir)
Results = Results.AddRange(FindFiles(strDirectoryName, searchTerm)
Next
Return Results
End Function
Make a recursive function that keeps calling itself until all subdirectories are checked:
Private Function GetAllFileNamesFromDirectory(ByVal strPath As String, ByVal strSearchTerm As String) As List(Of String)
Dim lstFileNames As New List(Of String)
Dim lstSubDirectories As List(Of String) = IO.Directory.GetDirectories(strPath).ToList()
Dim lstFilesToAdd As List(Of String) = IO.Directory.GetFiles(strPath).ToList()
For Each strFileToAdd As String In lstFilesToAdd
If strFileToAdd.Contains(strSearchTerm) Then
'Additional logic would be required to filter out the directory name.
lstFileNames.Add(strFileToAdd)
End If
Next
If lstSubDirectories.Count > 0 Then
lstSubDirectories.ForEach(Sub(strDirectoryPath As String)
Dim lstSubDirectoryFilesToAdd As List(Of String) = GetAllFileNamesFromDirectory(strDirectoryPath, strSearchTerm)
If lstSubDirectoryFilesToAdd.Count > 0 Then
lstFileNames.AddRange(lstSubDirectoryFilesToAdd)
End If
End Sub)
End If
Return lstFileNames
End Function

Search In a Directory and Subdirectories and List All Matched Files and Folder

I want Search In a Directory for multiple pattern ( For Example : *.jpg,*.png,Davood,*.dj ) that Result shoud return all files and folders that matched with my pattern,
can any body help to me ?
Thanks in advance
Modified to search multiple pattherns
Dim Patterns As String() = yourPatterns.Split(","c)
Dim matchedDirectories As New List(Of String)
Dim matchedFiles As New List(Of String)
For Each pattern in Patterns
Dim targetDirectory As New System.IO.DirectoryInfo(yourDirectoryPath)
Dim yourPatternToMatch As String = pattern
matchedDirectories.Concat(targetDirectory.GetDirectories(yourPatternToMatch, System.IO.SearchOption.AllDirectories).AsEnumerable.Select(Function(d) d.FullName)))
matchedFiles.Concat(targetDirectory.GetFiles(yourPatternToMatch, System.IO.SearchOption.AllDirectories).AsEnumerable.Select(Function(f) f.FullName))
Next
return matchedDirectories.Concat(matchedFiles)
This will return a List(Of String) that match yourPatternToMatch

String() variable in VB

I'm trying to modify a program where there is a variable that stores all the specified file types in a String() variable. What I would like to do is to somehow append to this variable in any way if I want to search another directory or just grab another individual file. Any suggestions would be greatly appreciated.
//Grab files from a directory with the *.txt or *.log as specified in the Combo Box
Dim strFiles As String()
strFiles = System.IO.Directory.GetFiles(txtSource.Text, cmbtype.SelectedItem, IO.SearchOption.AllDirectories)
EDIT: Edited to include code snippet used.
Dim strFiles As String()
Dim listFiles As List(Of String)(strFiles)
If (cmbtype.SelectedItem = "All") Then
//Do stuff
For index As Integer = 1 To cmbtype.Items.Count - 1
Dim strFileTypes As String() = System.IO.Directory.GetFiles(txtSource.Text, cmbtype.Items(index), IO.SearchOption.AllDirectories)
Next
//Exit Sub
Else
listFiles.Add(System.IO.Directory.GetFiles(txtSource.Text, cmbtype.SelectedItem, IO.SearchOption.AllDirectories).ToString())
End If
Right now you're using a String() which is an array of String instances. Arrays are not well suited for dynamically growing structures. A much better type is List(Of String). It is used in very similar manners to a String() but has a handy Add and AddRange method for appending data to the end.
Dim strFiles As New List(Of String)()
strFiles.AddRange(System.IO.Directory.GetFiles(txtSource.Text, cmbtype.SelectedItem, I
O.SearchOption.AllDirectories)
dim listFiles as list(of string)
listFiles = System.IO.Directory.GetFiles(txtSource.Text, cmbtype.SelectedItem, IO.SearchOption.AllDirectories).ToList()
listFiles.Add("..\blah\...\")

VB.NET - Load a List of Values from a Text File

I Have a text file that is like the following:
[group1]
value1
value2
value3
[group2]
value1
value2
[group3]
value3
value 4
etc
What I want to be able to do, is load the values into an array (or list?) based on a passed in group value. eg. If i pass in "group2", then it would return a list of "value1" and "value2".
Also these values don't change that often (maybe every 6 months or so), so is there a better way to store them instead of a plain old text file so that it makes it faster to load etc?
Thanks for your help.
Leddo
This is a home work question?
Use the StreamReader class to read the file (you will need to probably use .EndOfStream and ReadLine()) and use the String class for the string manipulation (probably .StartsWith(), .Substring() and .Split().
As for the better way to store them "IT DEPENDS". How many groups will you have, how many values will there be, how often is the data accessed, etc. It's possible that the original wording of the question will give us a better clue about what they were after hear.
Addition:
So, assuming this program/service is up and running all day, and that the file isn't very large, then you probably want to read the file just once into a Dictionary(of String, List(of String)). The ContainsKey method of this will determine if a group exists.
Function GetValueSet(ByVal filename As String) As Dictionary(Of String, List(Of String))
Dim valueSet = New Dictionary(Of String, List(Of String))()
Dim lines = System.IO.File.ReadAllLines(filename)
Dim header As String
Dim values As List(Of String) = Nothing
For Each line As String In lines
If line.StartsWith("[") Then
If Not values Is Nothing Then
valueSet.add(header, values)
End If
header = GetHeader(line)
values = New List(Of String)()
ElseIf Not values Is Nothing Then
Dim value As String = line.Trim()
If value <> "" Then
values.Add(value)
End If
End If
Next
If Not values Is Nothing Then
valueSet.add(header, values)
End If
Return valueSet
End Function
Function GetHeader(ByVal line As String)
Dim index As Integer = line.IndexOf("]")
Return line.Substring(1, index - 1)
End Function
Addition:
Now if your running a multi-threaded solution (that includes all ASP.Net solutions) then you either want to make sure you do this at the application start up (for ASP.Net that's in Global.asax, I think it's ApplicationStart or OnStart or something), or you will need locking. WinForms and Services are by default not multi-threaded.
Also, if the file changes you need to restart the app/service/web-site or you will need to add a file watcher to reload the data (and then multi-threading will need locking because this is not longer confined to application startup).
ok, here is what I edned up coding:
Public Function FillFromFile(ByVal vFileName As String, ByVal vGroupName As String) As List(Of String)
' open the file
' read the entire file into memory
' find the starting group name
Dim blnFoundHeading As Boolean = False
Dim lstValues As New List(Of String)
Dim lines() As String = IO.File.ReadAllLines(vFileName)
For Each line As String In lines
If line.ToLower.Contains("[" & vGroupName.ToLower & "]") Then
' found the heading, now start loading the lines into the list until the next heading
blnFoundHeading = True
ElseIf line.Contains("[") Then
If blnFoundHeading Then
' we are at the end so exit the loop
Exit For
Else
' its another group so keep going
End If
Else
If blnFoundHeading And line.Trim.Length > 0 Then
lstValues.Add(line.Trim)
End If
End If
Next
Return lstValues
End Function
Regarding a possible better way to store the data: you might find XML useful. It is ridiculously easy to read XML data into a DataTable object.
Example:
Dim dtTest As New System.Data.DataTable
dtTest.ReadXml("YourFilePathNameGoesHere.xml")