VB.Net - How to Change attributes of Folder included sub folder & files - vb.net

How to change or remove attribute of selected folder including all sub folders & files.
I used the following code :
System.IO.SetAttribute(FolderBrowserDialog1.SelectedPath,IO.FileAttribute.Hidden)
But it changes only selected folder attributes not sub folders & files

All subfolders and files can be enumerated like this:
If FolderBrowserDialog1.ShowDialog = DialogResult.OK Then
Dim di = New IO.DirectoryInfo(FolderBrowserDialog1.SelectedPath)
di.Attributes = di.Attributes Or FileAttributes.Hidden
For Each i In di.EnumerateFileSystemInfos("*", SearchOption.AllDirectories)
i.Attributes = i.Attributes Or FileAttributes.Hidden
Next
End If
Another way can be with attrib.exe:
Dim cmd = "attrib +H """ & FolderBrowserDialog1.SelectedPath.TrimEnd("\"c)
Shell("cmd /c " & cmd & """ & " & cmd & "\*"" /S /D", AppWinStyle.Hide)
I expect it to be faster than enumerating all file entries and getting and setting the attributes of each one separately, but another advantage of this method is that by default the shell function does not wait for the command to complete and your program can continue without waiting.

You can loop over subfolder recursively. I think that OS do that recursively too!!
Private Function getAllFolders(ByVal directory As String) As List(of String)
'Create object
Dim fi As New IO.DirectoryInfo(directory)
'Change main folder attribute
System.IO.SetAttribute(directory,IO.FileAttribute.Hidden )
'List to store paths
Dim Folders As New List(Of String)
'Loop through subfolders
For Each subfolder As IO.DirectoryInfo In fi.GetDirectories()
'Add this folders name
Folders.Add(subfolder.FullName)
'Recall function with each subdirectory
For Each s As String In getAllFolders(subfolder.FullName)
Folders.Add(s)
'Change subfolders attribute
System.IO.SetAttribute(s,IO.FileAttribute.Hidden )
Next
Next
Return Folders
End Function

Related

Iterate through a directory to get subfolders and certain files

I am working on a program that will move files to a database, text files to be exact. The user will have a starting directory and inside will multiple sub folders and files and so on. I want to go through each Folder and sub folder looking for the text files and add them accordingly to the database so it resembles a directory structure in a way. In the program the files are organized such as the folders are "Categories" that are displayed into a tree view.I am only adding the folder names(as Categories) that do contain text files and their subs and so forth. As well I need to figure out where to plug in the adding of the "Category". As of right now I am using a couple of listboxes for my output until I can get it all figured out.
lstfiles.Items.Add(Dir)
For Each file In System.IO.Directory.GetFiles(Dir)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
AddFile(file, Gennumber(9999))
End If
End If
Next
For Each folder In System.IO.Directory.GetDirectories(Dir)
lstfiles.Items.Add(folder)
For Each file In System.IO.Directory.GetFiles(folder)
Dim fi As System.IO.FileInfo = New IO.FileInfo(file)
If fi.Extension = ".txt" Then
If lstRootFolderFiles.Items.Contains(file) = False Then
lstfiles.Items.Add(file)
End If
End If
Next
Next
I have gotten so far as to iterate through the directory and get files but it returns folders that are empty. And I need to figure out where I need to put in my addcategory function. And also remember the last one that was added so they can be added as a subcategory.
I think I am making a big mess of it all, or over thinking the whole thing.
Any assistance or guidance would be appreciated.Thank you
The end result that I came up with was much different from my original posting, as it was my way of thinking of how it was going to work. I split up the two main functions. Retrieving the Folders and retrieving the files.
DirEx is the Import Directory, CatID is the Tag of the selected Treenode where the folders are going to added in.
Private Sub DirImport_GetSubDirectories(ByVal DirEx As String, ByVal CatID As Integer)
Try
Dim ClsData As New clsNoteData
'Set the DatabaseFile Property of the class
ClsData.Database = LoadedLibraryDatabase
' Get all subdirectories
Dim subdirectoryEntries() As String = Directory.GetDirectories(DirEx)
' Loop through them to see if they have any other subdirectories
Dim subdirectory As String
For Each subdirectory In subdirectoryEntries
'If the Directory is not Empty
If Not Directory.GetFileSystemEntries(subdirectory).Length = 0 Then
Dim di As DirectoryInfo = New DirectoryInfo(subdirectory)
'Creating Random Number
Dim NewCatID As Integer = GenNumber(9999)
'Call for a new Sub Category
ClsData.NewSubCategoryNode(LoadedLibraryDatabase, NewCatID, CatID, di.Name, -1)
'Get files in the current Directory
DirImport_GetFiles(subdirectory, NewCatID)
'Get the next set of Subfolders
DirImport_GetSubDirectories(subdirectory, NewCatID)
End If
Next
Catch ex As Exception
End Try
End Sub
Private Sub DirImport_GetFiles(ByVal DirEx As String, ByVal CatID As Integer)
Dim Files() As String = Directory.GetFiles(DirEx, "*.txt")
Dim file As String
For Each file In Files
Dim clsNoteData As New clsNoteData
Dim fi As FileInfo = New FileInfo(file)
clsNoteData.Database = LoadedLibraryDatabase
clsNoteData.NewNote_ID = GenNumber(99999)
clsNoteData.NewNote_CatID = CatID
clsNoteData.NewNote_Title = Path.GetFileNameWithoutExtension(file)
clsNoteData.NewNote(False, file)
Next
End sub
So here it is for anyone who may want to do something similar.

Can multiple files be moved in as a batch

I want to move multiple files from one directoy to anoher. I use 'My.Computer.FileSystem.MoveFile' and that works fine but it handles one file at a time. So, for every already existing file in that directory I get a warning (ie. 'File already exists') instead of one warning for the batch. Is it posible to get one warning for all the moved files?
For i = .Items.Count - 1 To 0 Step -1
Dim map = .Items.Item(i).SubItems(COL_MAP).Text
Dim bestandHernoemd = .Items.Item(i).SubItems(COL_HERNOEMD).Text
Dim bestandOrigineel = .Items.Item(i).SubItems(COL_ORIGINEEL).Text
Try
My.Computer.FileSystem.MoveFile(map & bestandOrigineel, My.Settings.OPTIE_OvernemenStandaardMapNaam & bestandHernoemd, Microsoft.VisualBasic.FileIO.UIOption.AllDialogs, Microsoft.VisualBasic.FileIO.UICancelOption.ThrowException)
.Items.RemoveAt(i)
Catch ex As Exception
foutLijst.Add(bestandOrigineel & ": " & ex.Message)
End Try
Next
And if you want to copy files recursively ( all folders, subfolders, files or subfiles ) from one source to destination, you can use the below sub procedure. No Warning applied and shall overwrite the destination.
Public Sub CopyDirectory(ByVal sourcePath As String, ByVal destinationPath As String)
Dim sourceDirectoryInfo As New System.IO.DirectoryInfo(sourcePath)
'If the destination folder doesn't exist then create it'
If Not System.IO.Directory.Exists(destinationPath) Then
'Obs, folder doesn't exist, create one please :)'
System.IO.Directory.CreateDirectory(destinationPath)
End If
Dim fileSystemInfo As System.IO.FileSystemInfo
For Each fileSystemInfo In sourceDirectoryInfo.GetFileSystemInfos
Dim destinationFileName As String = System.IO.Path.Combine(destinationPath, fileSystemInfo.Name)
'Now check whether its a file or a folder and take action accordingly
If TypeOf fileSystemInfo Is System.IO.FileInfo Then
System.IO.File.Copy(fileSystemInfo.FullName, destinationFileName, True)
Else
' Recursively call the method to copy all the nested folders
CopyDirectory(fileSystemInfo.FullName, destinationFileName)
End If
Next
End Sub

Finding txt files inside a given folder with subfolders?

Can anyone tell me how can I find say *.txt files inside a given folder inside which there are subfolders in the structure 12345\30123\128\txt\100.txt, the main folder can contain other subfolders or txt files but I only want to get the txt files which reside in the subfolders of the format 12345\30123\128\txt\100.txt. i.e. txt files inside all txt folders
I have tried this:
Dim txtFilesArray As String() = Directory.GetFiles(targetDirectory, "*.txt", SearchOption.AllDirectories)
But it gets all txt files?
Dim txtFiles = Directory.EnumerateFiles(targetDirectory,"*.txt",SearchOption.AllDirectories)
.Where(Function(f) f Like "*\#*\#*\#*\txt\#*.txt")
where # matches any digit from 0 to 9 and * matches any 0 or more characters
or slower RegEx version will be something like
Dim txtFiles = Directory.EnumerateFiles(targetDirectory,"*.txt",SearchOption.AllDirectories)
.Where(Function(f) RegEx.IsMatch(f, ".*\\\d+\\\d+\\\d+\\txt\\\\d+\.txt"))
For Each txtFile In txtFiles
'...
Next
This will return all files but those contained at path:
Dim path = "C:\"
Dim di As New DirectoryInfo(path)
Dim files = di _
.GetFiles("*.txt", SearchOption.AllDirectories) _
.Where(Function(info) info.DirectoryName <> path) _
.Select(function(info) info.FullName) _
.ToArray()

How to read files in folders?

I am trying to get my application to check for folders in the folderbrowserdialogs selectedpath and then get those files, but it doesn't work I have tried both listed ways below. The second way gives me an error: (Expression is of type char which is not a collection type)
For Each folder In FileBrowserDialog.SelectedPath
Dim counter As _
System.Collections.ObjectModel.ReadOnlyCollection(Of String)
counter = My.Computer.FileSystem.GetFiles(folder)
Label1.Text = counter.Count.ToString
Next
For Each folder In FileBrowserDialog.SelectedPath
Dim counter As _
System.Collections.ObjectModel.ReadOnlyCollection(Of String)
For Each foundfile In folder
counter = My.Computer.FileSystem.GetFiles(foundfile)
Label1.Text = counter.Count.ToString
Next
Any help is appreciated.
FolderBrowserDialog1.SelectedPath will return the path the user selected in the dialog. You still need to write code to go get the files. There may not be a need to get the folders and then files in them. Net has ways to do that for you:
FolderBrowserDialog1.ShowDialog()
Dim myPath As String = FolderBrowserDialog1.SelectedPath
' get all files for a folder
Dim files = Directory.GetFiles(myPath)
' get all files for all sub folders
Dim files = Directory.GetFiles(myPath, "*.*",
System.IO.SearchOption.AllDirectories)
' get certain file types for folder and subs
Dim files = Directory.GetFiles(myPath, "*.jpg",
System.IO.SearchOption.AllDirectories)
You also are not going to be able to simply assign the results to a ReadOnlyCollection like that, because they are ReadOnly. The collection needs to be created/instanced with the complete list:
Dim counter As new ReadOnlyCollection(Of String)(files)

VB.NET - Rename all the folders (And sub folders) in a selected folder

I tried to practise, search and i didn't find a solution to how to rename all the folders and sub-folders in a desired folder. For example i want to loop trough all the folders and add "_test" to the end, i searched, practiced and i didn't find any great solution so i'm asking to you if you have any snippet of code, or just and idea. I started with creating an array of all the folders within a folder by doing that:
Dim folderArray() As String = IO.Directory.GetDirectories(TextBoxPath.Text, "*", IO.SearchOption.AllDirectories)
For Each folder In folderArray
Dim infoParent As New IO.DirectoryInfo(folder)
Dim folderParent = infoParent.Parent.FullName
Dim folderName = folder.Split(IO.Path.DirectorySeparatorChar).Last()
FileSystem.Rename(folder, folderParent & "\" & folderName & "_Test")
Next
But that's not working, because i rename the directories, so the array is not valid (folderArray) because it has the old directory path.
If you have a way to do it, i'm opened to suggestions, thanks.
I would try do it recursively to make sure it's done at the bottom-most level first. (might not be 100% correct code, but just to give the general idea)
Sub RenameFolderRecursive(path As String)
For Each f As String In IO.Directory.GetDirectories(path)
RenameFolderRecursive(f)
Next
IO.Directory.Move(path, path & "_test")
End Sub
See if that works.
This sounds like a job for recursion. Since you don't know how many folders any given folder will contain, or how many levels deep a folder structure can be, you can't just loop through it. Instead, write a function which solves a discrete piece of the overall problem and recurse that function. My VB is very rusty so this might not be 100% valid (you'll definitely want to debug it a bit), but the idea is something like this:
Function RenameFolderAndSubFolders(ByVal folder as String)
' Get the sub-folders of the current folder
Dim subFolders() As String = IO.Directory.GetDirectories(folder, "*", IO.SearchOption.AllDirectories)
If subFolders.Length < 1 Then
'This is a leaf node, rename it and return
FileSystem.Rename(folder, folder & "_Test")
Return
End If
' Recurse on all the sub-folders
For Each subFolder in subFolders
RenameFolderAndSubFolders(subFolder)
' Rename the current folder once the recursion is done
FileSystem.Rename(subFolder, subFolder & "_Test")
Next
End Function
The idea here is simple. Given a folder name, get all of the child folders. If there aren't any, rename that folder. If there are, recurse the same function on them. This should find all of the folders and rename them accordingly. To kick off the process, just call the function on the root folder of the directory tree you want renamed.
Sub RenameAll(ByVal sDir As String)
Try
For Each d As String In Directory.GetDirectories(sDir)
IO.Directory.Move(d, d & "_test")
RenameAll(d & "_test")
Next
Catch x As System.Exception
End Try
End Sub
Here is recursive function that might do the job you need.
Private Sub RenameAllFolds(d As String)
Dim subfolds() As String = IO.Directory.GetDirectories(d)
If subfolds.Count = 0 Then
IO.Directory.Move(d, d & "_Test")
Else
For Each dir As String In subfolds
RenameAllFolds(dir)
Next
IO.Directory.Move(d, d & "_Test")
End If
End Sub
Sub Main()
Dim inf As String = "C:\renametest"
Dim folds() As String = IO.Directory.GetDirectories(inf)
For Each f As String In folds
RenameAllFolds(f)
Next
Console.ReadKey()
End Sub