I have this problem that i cant seem to overcome. i am trying to list all the directories and sub directories. This is what i have so far in code :
String[] Folders;
String[] Files;
path = Server.MapPath("/");
DirectoryInfo dir = new DirectoryInfo(path);
Folders = Directory.GetDirectories(path);
try
{
FolderListing.Append("<ul id=\"FolderList\">");
for (int x = 0; x < Folders.Length; x++ )
{
DirectoryInfo folder = new DirectoryInfo(Folders[x]);
FolderListing.Append("<li>").Append(folder.Name).Append("</li>");
CheckSubdirectories(Folders[x]);
}
FolderListing.Append("</ul>");
FolderList.Text = FolderListing.ToString();
}
catch (Exception exc) //Module failed to load
{
Exceptions.ProcessModuleLoadException(this, exc);
}
}
private void CheckSubdirectories(string currentpath)
{
String[] subfolders = Directory.GetDirectories(currentpath);
if (subfolders.Length != 0)
{
FolderListing.Append("<ul id=\"SubFolderList\">");
}
for (int x = 0; x < subfolders.Length; x++ )
{
DirectoryInfo sfolder = new DirectoryInfo(subfolders[x]);
FolderListing.Append("<li>").Append(sfolder.Name).Append("</li>");
}
if (subfolders.Length != 0)
{
FolderListing.Append("</ul>");
}
path = currentpath.ToString();
}
i would like the end result to be :
<ul>
<li>admin</li>
<ul>
<li>Containers</li>
<li>ControlPanel</li>
<li>Menus</li>
<ul>
<li>etc etc</li>
</ul>
</ul>
</ul>
if anyone can help me please
Hope this recursive method helps:
void ListDirectories(string path, StringBuilder sb)
{
var directories = Directory.GetDirectories(path);
if (directories.Any())
{
sb.AppendLine("<ul>");
foreach (var directory in directories)
{
var di = new DirectoryInfo(directory);
sb.AppendFormat("<li>{0}</li>", di.Name);
sb.AppendLine();
ListDirectories(directory, sb);
}
sb.AppendLine("</ul>");
}
}
To invoke it, just create an instance of StringBuilder
and send it along with the path to the method:
var sb = new StringBuilder();
ListDirectories(Server.MapPath("/"), sb);
This works:
Func<DirectoryInfo, XElement[]> getDirectories = null;
getDirectories = di =>
(new []
{
new XElement("li", di.Name),
di.GetDirectories().Any()
? new XElement("ul",
from cdi in di.GetDirectories()
select getDirectories(cdi))
: null,
})
.Where(x => x != null)
.ToArray();
var xml = new XElement("ul",
getDirectories(
new DirectoryInfo(@"E:\Install\_.NET")));
From my example directory I got this output:
<ul>
<li>_.NET</li>
<ul>
<li>3DCollaborator</li>
<li>MercurialVSSProvider</li>
<li>MongoDB</li>
<li>sqlite</li>
<ul>
<li>sqlite-netFx35-binary-bundle-Win32-2008-1.0.74.0</li>
<li>sqlite-netFx35-binary-Win32-2008-1.0.74.0</li>
<li>sqlite-netFx40-binary-Win32-2010-1.0.74.0</li>
</ul>
</ul>
</ul>
You can solve the problem by using a recursive approach. You need a method that calls itself in order to list subdirectories that are nested at any depth.
public ListDirectory (DirectoryInfo dir)
{
//TODO: Output the directory info here.
foreach (DirectoryInfo subdir in dir.Directories) {
ListDirectory(subdir);
}
foreach (FileInfo file in dir.Files) {
//TODO: Output the file info here.
}
}
The list should look like this in HTML. Note that a subdirectory's <li>
must enclose the whole nested <ul>
.
<ul>
<li>subdirectory item 1
<ul>
<li>file 1 in subdirectory</li>
<li>file 2 in subdirectory</li>
</ul>
</li>
<li>subdirectory item 2
<ul>
<li>sub-subdirectory item
<ul>
<li>file 1 in sub-subdirectory</li>
<li>file 2 in sub-subdirectory</li>
</ul>
</li>
<li>file 1 in subdirectory</li>
<li>file 2 in subdirectory</li>
</ul>
</li>
<li>file item 1</li>
<li>file item 2</li>
</ul>
This will produce the following output:
- subdirectory item 1
- file 1 in subdirectory
- file 2 in subdirectory
- subdirectory item 2
- sub-subdirectory item
- file 1 in sub-subdirectory
- file 2 in sub-subdirectory
- file 1 in subdirectory
- file 2 in subdirectory
- file item 1
- file item 2
With this information, we can refine the method above (in pseudo-code)
public ListDirectory (DirectoryInfo dir)
{
Output("<li>"); Output(dir.Name);
if (dir.Directories.Count > 0 || dir.Files.Count > 0) {
Output("<ul>");
foreach (DirectoryInfo subdir in dir.Directories) {
ListDirectory(subdir);
}
foreach (FileInfo file in dir.Files) {
Output("<li>"); Output(file.Name); Output("</li>");
}
Output("</ul>");
}
Output("</li>");
}
You also will have to enclose the whole thing in a <ul> </ul>
pair. Also, you could use a slightly different scheme on the first level, in order to list files and directories instead of just one root directory, as my code above would.