How can I get the Google drive folder hierarchy? [duplicate] - c#

i am new with Nodes here.. :) i came up with this algorithm but it only shows the list of parent nodes.. like this..
a
a.txt
b
c
c
m
n
b
o
p
etc...
i want the next node will be put in one of the node inside the previous node.. so it will come up like this..
a
a.txt
b
o
p
c
m
n
etc...
i have some ideas in mind but i can implement it to codes.. :) any help please..
private void ListDirectory(TreeView treeView, String path)
{
Stack<string> stack = new Stack<string>();
TreeNode DirFilesCollection = new TreeNode();
stack.Push(path);
while (stack.Count > 0)
{
string dir = stack.Pop();
try
{
List<String> parentDir = new List<string>();
parentDir.AddRange(Directory.GetFiles(dir, "*.*"));
parentDir.AddRange(Directory.GetDirectories(dir));
DirectoryInfo d = new DirectoryInfo(dir);
TreeNode TParent = new TreeNode(d.Name);
foreach (String s in parentDir)
{
FileInfo f = new FileInfo(s);
TreeNode subItems = new TreeNode(f.Name);
TParent.Nodes.Add(subItems);
}
DirFilesCollection.Nodes.Add(TParent);
foreach (string dn in Directory.GetDirectories(dir))
{
stack.Push(dn);
}
}
catch
{}
}
Action clearTreeView = () => treeView.Nodes.Clear();
this.Invoke(clearTreeView);
Action showTreeView = () => treeView.Nodes.Add(DirFilesCollection);
this.Invoke(showTreeView);
}

Option #1: Recursive approach:
private void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var rootDirectoryInfo = new DirectoryInfo(path);
treeView.Nodes.Add(CreateDirectoryNode(rootDirectoryInfo));
}
private static TreeNode CreateDirectoryNode(DirectoryInfo directoryInfo)
{
var directoryNode = new TreeNode(directoryInfo.Name);
foreach (var directory in directoryInfo.GetDirectories())
directoryNode.Nodes.Add(CreateDirectoryNode(directory));
foreach (var file in directoryInfo.GetFiles())
directoryNode.Nodes.Add(new TreeNode(file.Name));
return directoryNode;
}
Option #2: Non-recursive approach:
private static void ListDirectory(TreeView treeView, string path)
{
treeView.Nodes.Clear();
var stack = new Stack<TreeNode>();
var rootDirectory = new DirectoryInfo(path);
var node = new TreeNode(rootDirectory.Name) { Tag = rootDirectory };
stack.Push(node);
while (stack.Count > 0)
{
var currentNode = stack.Pop();
var directoryInfo = (DirectoryInfo)currentNode.Tag;
foreach (var directory in directoryInfo.GetDirectories())
{
var childDirectoryNode = new TreeNode(directory.Name) { Tag = directory };
currentNode.Nodes.Add(childDirectoryNode);
stack.Push(childDirectoryNode);
}
foreach (var file in directoryInfo.GetFiles())
currentNode.Nodes.Add(new TreeNode(file.Name));
}
treeView.Nodes.Add(node);
}

Related

Enumerate directories that match wildcard

This is my folder structure:
c:\logs\v1\api1
c:\logs\v1\api2
c:\logs\v2\api1
c:\logs\v2\api2
c:\logs\other
I would like to get all folders that match this pattern:
c:\logs\v*\api*
So, what I want is to get list of theese:
c:\logs\v1\api1
c:\logs\v1\api2
c:\logs\v2\api1
c:\logs\v2\api2
This doesn't work:
var result = Directory.GetDirectories(#"c:\logs\v*\api*");
Because System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. : 'c:\logs\v*\api*'' is thrown
This doesn't work:
var directory = #"c:\logs\v*\api*";
var rootDirectory = Directory.GetDirectoryRoot(directory);
var remainingPath = directory.Substring(rootDirectory.Length);
Console.WriteLine($"remainingPath: {remainingPath}");
var result = Directory.GetDirectories(rootDirectory, remainingPath);
Because System.IO.IOException: 'The filename, directory name, or volume label syntax is incorrect. : 'c:\logs\v*'' is thrown
This works:
public static IEnumerable<string> ResolveDirectories(string path)
{
if (path.Contains("*") || path.Contains("?"))
{
var parts = new Regex(#"[\\/](?=[^\\/]*[\*?])").Split(path, 2);
var searchRoot = parts[0];
var searchPatterns = parts[1].Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar);
foreach (var dir in ResolveWildcards(searchRoot, searchPatterns))
yield return dir;
}
else
{
yield return path;
}
}
public static IEnumerable<string> ResolveWildcards(string searchRoot, string[] searchPatterns)
{
if (Directory.Exists(searchRoot))
{
// use next pattern to search in a search root
var next = searchPatterns[0];
// leave the rest for recursion
var rest = searchPatterns.Skip(1).ToArray();
if (!searchRoot.EndsWith("\\"))
searchRoot += "\\";
foreach (var dir in Directory.EnumerateDirectories(searchRoot, next))
{
// if nothing left (last pattern) - return it
if (rest.Length == 0)
yield return dir;
else
{
// otherwise search with rest patterns in freshly found directory
foreach (var sub in ResolveWildcards(dir, rest))
yield return sub;
}
}
}
}
But I don't like how this is coded.
Thanks to #Alessandro_D'Andria I created this:
public static IEnumerable<string> ResolveDirectories(string path)
{
var parts = new Regex(#"[\\/](?=[^\\/]*[\*?])").Split(path, 2);
var root = parts[0];
var part = #".*\\" + parts[1].Replace(#"\", #"\\");
var regex = new Regex(part);
var dirs = Directory
.EnumerateDirectories(
root,
"*",
SearchOption.AllDirectories)
.Where(x => regex.IsMatch(x))
.ToList();
return dirs;
}
But both solutions are big mess. Is there any more elegant solution?
I think you are complicating, just using some regex and linq should be enough:
var regex = new Regex(#".*\\logs\\v\d+\\api\d+");
var dirs = Directory
.EnumerateDirectories(
#"C:\logs",
"*",
SearchOption.AllDirectories)
.Where(x => regex.IsMatch(x));

Obtain all files that are over 1gb in C#

I'm trying to get all the non system files on my computer to find out what files are over 1gb via a WinForms application.
Here is the code I'm working with:
const long b500mb = 65536000;
const long b1gb = 134217728;
public Main()
{
InitializeComponent();
}
//https://unitconverter.io/gigabits/bytes/1
private void Main_Load(object sender, EventArgs e)
{
var cDriveDirectories = new DirectoryInfo(#"C:\").GetDirectories()
.Where(f => !f.Attributes.HasFlag(FileAttributes.System))
.Where(w => w.FullName != #"C:\Windows")
.Select(f => f.FullName)
.ToList();
var filesOver1Gb = new List<FileInfo>();
foreach (var item in cDriveDirectories)
{
DirectoryInfo d = new DirectoryInfo(item);
var files = d.GetFiles("*", SearchOption.AllDirectories).Where(w => w.Attributes.HasFlag(FileAttributes.Normal)
&& w.Length > b1gb).ToList();
foreach (FileInfo file in files)
{
filesOver1Gb.Add(file);
}
}
}
How can I get around this error?
System.UnauthorizedAccessException: 'Access to the path 'C:\inetpub\history' is denied.'
After #zee's help:
I VS as an admin and then put a try/catch around the line of code that was failing and continued.
This code will obtain the information I need!
const long b500mb = 65536000;
const long b1gb = 134217728;
public Main()
{
InitializeComponent();
}
//https://unitconverter.io/gigabits/bytes/1
private void Main_Load(object sender, EventArgs e)
{
var cDriveDirectories = new DirectoryInfo(#"C:\").GetDirectories()
.Where(f => !f.Attributes.HasFlag(FileAttributes.System))
.Where(w => w.FullName != #"C:\Windows")
.Select(f => f.FullName)
.ToList();
var filesOver1Gb = new List<FileInfo>();
IList<string> unauthorizedFiles = new List<string>();
foreach (var item in cDriveDirectories)
{
DirectoryInfo d = new DirectoryInfo(item);
var files = new List<FileInfo>();
try
{
files = d.GetFiles("*", SearchOption.AllDirectories).Where(w => !w.Attributes.HasFlag(FileAttributes.System)
&& w.Length > b1gb).ToList();
}
catch (UnauthorizedAccessException)
{
// ignore error and continue to process files over 1gb.
}
foreach (FileInfo file in files)
{
filesOver1Gb.Add(file);
}
}
// get the total count in bytes to find out how many gbs we have etc.
long totalOver1Gb = 0;
foreach (var file in filesOver1Gb)
{
totalOver1Gb = totalOver1Gb + file.Length;
}
}

How can I loop over sub folders in Assets folder?

string selectedPath = GetPath();
var subFolders = AssetDatabase.GetSubFolders(selectedPath);
List<string> paths = new List<string>();
foreach(string path in subFolders)
{
paths.Add(path);
}
For example the subFolders is Assets/My Folder
but under My Folder there are many more subfolders.
AssetDatabase.GetSubFolders don't make recursive it's getting the first sub folder only.
I want to get all the sub folders recursive.
I tried :
List paths = new List();
foreach(string path in subFolders)
{
paths.Add(path);
}
but it's still giving me only the first sub folder.
This is how I'm getting the selected path name in the Assets :
[MenuItem("Assets/Get Path")]
private static string GetClickedDirFullPath()
{
string clickedAssetGuid = Selection.assetGUIDs[0];
string clickedPath = AssetDatabase.GUIDToAssetPath(clickedAssetGuid);
string clickedPathFull = Path.Combine(Directory.GetCurrentDirectory(), clickedPath);
FileAttributes attr = File.GetAttributes(clickedPathFull);
return attr.HasFlag(FileAttributes.Directory) ? clickedPathFull : Path.GetDirectoryName(clickedPathFull);
}
[MenuItem("Assets/Get Path")]
private static string GetPath()
{
string path = GetClickedDirFullPath();
int index = path.IndexOf("Assets");
string result = path.Substring(index);
return result;
}
You could simply make it recursive using List<T>.AddRange like
private static string[] GetSubFoldersRecursive(string root)
{
var paths = new List<string>();
// If there are no further subfolders then AssetDatabase.GetSubFolders returns
// an empty array => foreach will not be executed
// This is the exit point for the recursion
foreach (var path in AssetDatabase.GetSubFolders(root))
{
// add this subfolder itself
paths.Add(path);
// If this has no further subfolders then simply no new elements are added
paths.AddRange(GetSubFoldersRecursive(path));
}
return paths.ToArray();
}
So e.g.
[ContextMenu("Test")]
private void Test()
{
var sb = new StringBuilder();
var folders = SubFolders("Assets");
if(folders.Length > 0)
{
foreach (var folder in SubFolders("Assets"))
{
sb.Append(folder).Append('\n');
}
}
else
{
sb.Append(" << The given path has no subfolders! >>");
}
Debug.Log(sb.ToString());
}
will print out the entire project's folder structure.
For
I get
Assets/Example 1
Assets/Example 1/SubFolder A
Assets/Example 1/SubFolder B
Assets/Example 1/SubFolder C
Assets/Example 2
Assets/Example 2/SubFolder A
Assets/Example 2/SubFolder A/SubSubFolder A
So in your case it would be
string selectedPath = GetPath();
var folders = SubFolders(selectedPath);
foreach(var path in folders)
{
...
}
Try this code for get recursive folder path
//this is your code
string selectedPath = GetPath();
var subFolders = AssetDatabase.GetSubFolders(selectedPath);
List<string> paths = new List<string>();
if(subFolders != null)
{
foreach(string path in subFolders)
{
GetAllRecursiveFolder(path,ref paths);
}
}
else
{
paths.add(selectedPath);
}
public void GetAllRecursiveFolder(string currentPath,ref List<string> paths)
{
var subFolders = AssetDatabase.GetSubFolders(currentPath);
if(subFolders != null)
{
foreach(string path in subFolders)
{
GetAllRecursiveFolder(path,ref paths);// Get recursive folder path, and stored in ref variable
}
}
else
{
paths.add(currentPath);
}
}

Treeview with different folder classes

I'm trying to pull together a treeview with folders of mixed classes. The root folders are one class and subfolders are another, like this:
Root Folder #1 <-- DirectoryItem class
--Sub Folder <-- SubDirectoryItem class
----file <-- FileItem class
Root Folder #2 <-- DirectoryItem class
--Sub Folder <-- SubDirectoryItem class
----file <-- FileItem class
I've been attempting to combine two different recursive methods so the subfolders are retrieved as "SubDirectoryItems" instead of "DirectoryItem" I'll spare that code attempt due to lack of clarify, but I'm wondering if there's a better approach?
class ItemProvider
{
public List<Item> GetItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetItems(directory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var subdirectory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new SubDirectoryItem()
{
Name = subdirectory.Name,
Path = subdirectory.FullName,
Items = GetItems(subdirectory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var file in dirInfo.GetFiles())
{
var item = new FileItem
{
Name = file.Name,
Path = file.FullName
};
items.Add(item);
}
return items;
}
}
}
I was able to figure it out. I made the first list TopDirectoryOnly then pulled in the rest of the items via a 2nd list for AllDirectories. Here's the code in case it helps any other beginners (like me):
class ItemProvider
{
public List<Item> GetItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var directory in dirInfo.GetDirectories("*.*", SearchOption.TopDirectoryOnly))
{
var item = new DirectoryItem
{
Name = directory.Name,
Path = directory.FullName,
Items = GetSubItems(directory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
return items;
}
public List<Item> GetSubItems(string path, SearchOption searchOption)
{
var items = new List<Item>();
var dirInfo = new DirectoryInfo(path);
foreach (var subdirectory in dirInfo.GetDirectories("*.*", SearchOption.AllDirectories))
{
var item = new SubDirectoryItem()
{
Name = subdirectory.Name,
Path = subdirectory.FullName,
Items = GetSubItems(subdirectory.FullName, SearchOption.AllDirectories)
};
items.Add(item);
}
foreach (var file in dirInfo.GetFiles())
{
var item = new FileItem
{
Name = file.Name,
Path = file.FullName
};
items.Add(item);
}
return items;
}
}

Create WiX Msi with WiX Sharp

my WiX Sharp program for Creating msi:
static public void BuildMsi(string FolderPath)
{
string InstallationDirectoryPath = #"D:\Program";
var project = new Project("MyProduct",
new Dir(InstallationDirectoryPath,
new Files(System.IO.Path.Combine(FolderPath,"**"))));
Compiler.BuildMsi(project);
}
In this code if i pass the folder path which i want to release then it will create a msi that is working fine.
My Question is i want to pass multiple folder path so my main function looks like this but i am not able to figure out what i have to change in middle of the code
static public void BuildMsi(list<string> folderPath)
You could try something like this, but the code is not perfect..
It will get the main directory with files and all sub directories with files.
static string sRootDir = #"<Path of main directory>";
static public void BuildMsi(string FolderPath)
{
WixEntity[] weDir = new WixEntity[0];
weDir = BuildDirInfo(sRootDir, weDir);
var project = new Project("MyProduct", weDir);
Compiler.BuildMsi(project);
}
static WixEntity[] BuildDirInfo(string sRootDir, WixEntity[] weDir)
{
DirectoryInfo RootDirInfo = new DirectoryInfo(sRootDir);
if (RootDirInfo.Exists)
{
DirectoryInfo[] DirInfo = RootDirInfo.GetDirectories();
List<string> lMainDirs = new List<string>();
foreach (DirectoryInfo DirInfoSub in DirInfo)
lMainDirs.Add(DirInfoSub.FullName);
int cnt = lMainDirs.Count;
weDir = new WixEntity[cnt + 1];
if (cnt == 0)
weDir[0] = new DirFiles(RootDirInfo.FullName + #"\*.*");
else
{
weDir[cnt] = new DirFiles(RootDirInfo.FullName + #"\*.*");
for (int i = 0; i < cnt; i++)
{
DirectoryInfo RootSubDirInfo = new DirectoryInfo(lMainDirs[i]);
if (!RootSubDirInfo.Exists)
continue;
WixEntity[] weSubDir = new WixEntity[0];
weSubDir = BuildDirInfo(RootSubDirInfo.FullName, weSubDir);
weDir[i] = new Dir(RootSubDirInfo.Name, weSubDir);
}
}
}
return weDir;
}

Categories