How to loop through all files in a folder using C#

Someone asked me how to loop through all the files in a folder...
well just a quick sample recursive solution...

Update: Thanks to Avner's comment I've noticed that the original code I've posted here was vulnerable to File System Reparse Point issue.

What is File System Reparse Point issue ?
When compiling the code and running if you add a reparse point to (c:\temp\recursive1\recursive2 -> c:\temp\recursive1). After a few recursions you get “System.IO.IOException: The name of the file cannot be resolved by the system.”. At the time of failure it was looking for c:\temp\recursive1\recursive2\recursive2\recursive2\recursive2\recursive2\recursive2\recursive2\recursive2\rerecursive2\recursive2\recursive2

MS Press Writing Secure Code 2
pages 686-7 includes the following information regarding File System Reparse Point Issues:
 
"Starting in windows 2000 NFTS supports directory junctions. This is similar to a UNIX symbolic link that redirects a reference from one directory to another directory on the same machine. You can create and manage directory junctions using Linkd.exe a tool available in the Windows Resource Kit."

"Directory junctions present a threat to any application that does a recursive traversal of the directory structure."

"It is the responsibility of any application that scans the directory hierarchy and especially the responsibility of applications that make destructive changes recursively through the directory hierarchy to recognize directory junctions and avoid traversing through them, Because directory junctions are implementer using reparse points, applications should see if a directory has the FILE_REPARSE_POINT attribute set before processing that directory. Your code is safe if you do not process any directory with FILE_REPARSE_POINT set which you can verify with functions such as GetFileAttributes and lpFindFileData->dwFileAttributes in FindFirstFile."

While looking for a gui tool to create Symbolic files I've found Winbolic Link which can create NTFS Junction and Shell Links
The program 
creates these links using only built-in functionality of Windows. It does not extend or modify the functionality of Windows or the file system, or require any service to remain running to maintain functionality. It merely creates the special kinds of files and folders Windows already supports, but which Microsoft did not distribute tools to create.

You can see that now I've implemented the check for ReparsePoint and my code is safe again :-)

Ohad.

// How much deep to scan. (of course you can also pass it to the method)
const int HowDeepToScan=4;

public
static void ProcessDir(string sourceDir, int recursionLvl) 
{
  if (recursionLvl<=HowDeepToScan)
  {
    // Process the list of files found in the directory.
    string [] fileEntries = Directory.GetFiles(sourceDir);
    foreach(string fileName in fileEntries)
    {
       // do something with fileName
       Console.WriteLine(fileName);
    }

    // Recurse into subdirectories of this directory.
    string [] subdirEntries = Directory.GetDirectories(sourceDir);
    foreach(string subdir in subdirEntries)
       // Do not iterate through reparse points
       if ((File.GetAttributes(subdir) &
           
 FileAttributes.ReparsePoint) !=
                FileAttributes.ReparsePoint)

            ProcessDir(subdir,recursionLvl+1);
  }

}

16 Comments

  • Am I wrong or are you not paying any attention to the recursionLvl parameter in your code?

  • You are not wrong... you can control how many levels deep to scan... i just haven't implemented it....

  • One small problem that can arise here - starting with Windows 2000, NTFS allows you to have symbolic links and remount points in your filesystem. This means that my C:\Folder\Beep can actually be C:\ mounted under a different name - and possibly go into an endless loop if you don't specify a maximum depth. Working around this is a headache - to find out whether a folder is actually a remount point, you have to P/Invoke and get nasty.

  • Thats correct... there was a prob. and now its gone,

    I just fixed the code and... didn't have to use P/Invoke



    :-)

  • Cool, I didn't know you could access the IsReparsePoint property from managed code.

    I haven't been in a position to write filesystem-intensive code lately, so I never really got to use the full range of System.IO classes. In my mind, I'm still doing it with VBScript and the FileSystemObject. :)

  • Hi,

    Here is another way to get filenames from all files, including subdirectories (notice the SearchOption.AllDirectories parametre):

    // Process the list of files found in all directory.
    string [] fileEntries = Directory.GetFiles(sourceDir, "*", SearchOption.AllDirectories);
    foreach(string fileName in fileEntries)
    {
    // do something with fileName
    Console.WriteLine(fileName);
    }

    If you change the "*" to ex. "*.log" you will get all filenames that ends with ".log".

  • I have different folders with different files.how i can i read all files in to dataset.once if i read files i will not use folders path.please help me

  • What do I need to include for this code to fly?

  • Thanks that was really helpful for me

  • Hi, thanks for this code it worked really well.

  • Good and Helpful article.

  • private void SearchStuff(string Directory, string search)
    {
    DirectoryInfo test = new DirectoryInfo(Directory);
    DirectoryInfo[] sub = test.GetDirectories("*"+search+"*",SearchOption.AllDirectories);
    FileInfo[] sub2 = test.GetFiles("*" + search + "*", SearchOption.AllDirectories);

    int count = sub.Length + sub2.Length;
    ttlCount += sub.Length + sub2.Length;
    int a = 0;

    if (count > 0)
    {
    ListViewItem[] temp = new ListViewItem[count];
    for (int i = 0; i < sub.Length; i++)
    {
    temp[i] = new ListViewItem(new string[] { sub[i].Name, sub[i].FullName });
    }

    for (int i = sub.Length; i < count; i++)
    {
    temp[i] = new ListViewItem(new string[] { sub2[a].Name, sub2[a].FullName });
    a++;
    }
    listView1.Items.AddRange(temp);
    }

  • hi
    i want to access a folder in other system that is shared and check for files in that folder greater than 1mb and return the count using C# ... can any1 help??

  • Thanks for the post. Really helpful. Makes me look like a genius

  • hi i wrote a simple convertor tool from file server to web server in the local network .

    this code match file server folder and web server folder and than remove similar name and add two list boxes .


    i hope this code help every one .

    regards



    public void getFiles(string path)
    { int total_item_file_server=0;
    string[] fileEntries = Directory.GetFiles(path);
    foreach (string fileName in fileEntries)
    {
    patinent_images_server.Items.Add(fileName.Replace("j:\\images\\patinet\\","").Replace(".bmp",""));
    total_item_file_server++;
    }

    label3.Text += " total Item: " + total_item_file_server;
    }

    private void Form1_Load(object sender, EventArgs e)
    {
    getFiles("j:\\images\\patient\\");


    string[] fileEntries = Directory.GetFiles("R:\\");
    int total_item_web_server = 0;
    foreach (string fileName in fileEntries)
    {
    patient_images_web.Items.Add(fileName.Replace("R:\\","").Replace(".jpg",""));
    total_item_web_server++;
    }


    int removeitem=0;
    /* if u wanna match list boxes and if folder have a images remove from to listbox
    foreach (object i in patinet_images_web.Items)
    {
    if (patient_images_web.Items.Contains(i))
    {
    patient_images_server.Items.Remove(i);
    removeitem++;


    }

    }
    */
    label3.Text += " Removed : " + removeitem;

    label4.Text += " Total Item : " + total_item_web_server;

    }

    private void button3_Click(object sender, EventArgs e)
    {

    progressBar1.Minimum = 0;
    progressBar1.Maximum = patient_images_server.Items.Count;

    for (int i = 0; i < patient_images_server.Items.Count; i++)
    {
    textBox2.Text = "";

    if (progressBar1.Value == patient_images_server.Items.Count)
    {
    MessageBox.Show("Convert complate");

    }



    string image_path = "j:\\images\\patient\\" + patient_images_server.Items[i] + ".bmp";

    Image img = Image.FromFile(image_path.Replace(".BMP",""));


    img.Save("R:\\" + i + ".jpg", System.Drawing.Imaging.ImageFormat.Jpeg);
    textBox2.Text = "R:\\" + i + ".jpg";

    progressBar1.Value++;
    System.Threading.Thread.Sleep(50);
    System.GC.Collect();

    img.Dispose();



    }


    }

  • pls give real example of ur argement are sourceDir and recursionLvL
    public static void ProcessDir(string sourceDir, int recursionLvl)

Comments have been disabled for this content.