Finding Directories With Regular Expressions


This article uses the classes File and Directory, and regular expression capabilities, to report the number of files of each file type that exist in the specified directory path. The illustration also serves as a "clean-up" utility when the program encounters a file that has the .bak filename extension (i.e., a backup file), the program displays a Message Box asking the user whether that file should be removed, then responds appropriately to the user's input.

Use the following market controls to do the search in a WPF application.

C# find directory

When the user presses the Enter key or clicks the Search Directory button, the program invokes the method "btnSearch_Click" that searches recursively through the directory path that the user provides.

If the user inputs text in the TextBox then the Directory method "Exists" is called to determine whether that text is a valid directory path and name. If not, notify the user of the error.

If the user specifies a valid directory then the directory name is passed as an argument to the private method SearchDirectory. This method locates files that match the regular expression defined.

  1. // check for user input; default is current directory  
  2. if (this.txtPath.Text != "")  
  3. {  
  4.     // verify that user input is valid directory name  
  5.     if (Directory.Exists(this.txtPath.Text))  
  6.     {  
  7.         currentDirectory = this.txtPath.Text;  
  8.         // reset input text box and update display  
  9.         tbkCurrentDirectory.Text = currentDirectory;  
  10.     } // end if  
  11.     else  
  12.     {  
  13.         // show error if user does not specify valid directory  
  14.         MessageBox.Show("Invalid Directory""Error",  
  15.         MessageBoxButton.OK, MessageBoxImage.Error);  
  16.     }   
  17. }  
This regular expression matches any sequence of numbers or letters followed by a period and one or more letters. Notice the substring of the format"(?<extension>\w+)" in the argument to the Regex constructor. This indicates that the part of the string that matches "\w+" (in other words, the filename extension that appears after a period in the file name) should be placed in the regular expression variable named extension. This variable's value is retrieved later from the Match object "matchResult" to obtain the filename extension so we can summarize the types of files in the directory. 
  1. // regular expression for extensions matching pattern  
  2. Regex regularExpression = new Regex(@"[a-zA-Z0-9]+\.(?<extension>\w+)");  
  4. // stores regular-expression match result  
  5. Match matchResult;  
The Call Directory method Getdirectories to retrieve the names of all subdirectories that belong to the current directory.
  1. // get directories  
  2. directoryList = Directory.GetDirectories(currentDirectory);  
Call Directory method GetFiles to store in string array fileArray the names of files in the current directory.
  1. // get list of files in current directory  
  2. fileArray = Directory.GetFiles(currentDirectory);  
The foreach loop searches for all files with the extension .bak. The loop then calls SearchDirectory recursively for each subdirectory in the current directory. Eliminate the directory path, so the program can test only the file name when using the regular expression. Use the Regex method "Match" to match the regular expression with the file name, then assign the result to the Match object matchResult. If the match is successful then use the Match method "Result" to assign to the fileExtension the value of the regular expression variable extension from the object "matchResult". If the match is unsuccessful then set fileExtension to "[no extension]".
  1. // iterate through list of files  
  2. foreach (string myFile in fileArray)  
  3. {  
  4.    // remove directory path from file name  
  5.     fileName = myFile.Substring(myFile.LastIndexOf(@"\") + 1);  
  6.     // obtain result for regular-expression search  
  7.     matchResult = regularExpression.Match(fileName);  
  8.     // check for match  
  9.     if (matchResult.Success)  
  10.         fileExtension = matchResult.Result("${extension}");  
  11.     else  
  12.         fileExtension = "[no extension]";  
  14.    // store value from container  
  15.    if (found[fileExtension] == null)  
  16.        found.Add(fileExtension, "1");  
  17.    else  
  18.    {  
  19.        extensionCount = Int32.Parse(found[fileExtension]) + 1;  
  20.        found[fileExtension] = extensionCount.ToString();  
  21.    }  
  22.    // search for backup( .bak ) files  
  23.    if (fileExtension == "bak")  
  24.     {  
  25.        // prompt user to delete ( .bak ) file  
  26.         MessageBoxResult result = MessageBox.Show("Found backup file " + fileName + ". Delete?""Delete Backup", MessageBoxButton.YesNo, MessageBoxImage.Question);  
  28.      // delete file if user clicked 'yes'  
  29.      if (result == MessageBoxResult.Yes)  
  30.      {  
  31.          File.Delete(myFile);  
  32.          extensionCount = Int32.Parse(found["bak"]) - 1;  
  33.          found["bak"] = extensionCount.ToString();  
  34.     }// end if  
  35. }   
  36.          }  
  37.         // recursive call to search files in subdirectory  
  38.          foreach (string myDirectory in directoryList)  
  39.        SearchDirectory(myDirectory);  
Class "FileSearchForm" uses an instance of the class "NameValueCollection" to store each filename-extension type and the number of files for each type. A NameValueCollection (namespace "System.Collections.Specialized") contains a collection of key-value pairs of strings, and provides the method "Add" to add a key-value pair to the collection. The indexer for this class can index by the order of the items added or by the keys. Use the NameValueCollection found to determine whether this is the first occurrence of the filename extension (the expression returns null if the collection does not contain a key-value pair for the specified fileExtension). If this is the first occurrence then add that extension to "found" as a key with the value 1. Otherwise, increment the value associated with the extension in "found" to indicate another occurrence of that file extension, and assign the new value to the key-value pair.
  1. NameValueCollection found = new NameValueCollection();  
  2. // store value from container  
  4. if (found[fileExtension] == null)  
  5.     found.Add(fileExtension, "1");  
  6. else  
  7. {  
  8.     extensionCount = Int32.Parse(found[fileExtension]) + 1;  
  9.     found[fileExtension] = extensionCount.ToString();  
  10. }  

The following code determines whether fileExtension equals "bak", in other words whether the file is a backup file. If so then prompt the user to indicate whether the file should be removed; if the user clicks "Yes" then delete the file and decrement the value for the "bak" file type in "found".

  1. if (fileExtension == "bak")  
  2. {  
  3.    // prompt user to delete ( .bak ) file  
  4.    MessageBoxResult result = MessageBox.Show("Found backup file " + fileName + ". Delete?""Delete Backup", MessageBoxButton.YesNo, MessageBoxImage.Question);   
  5.     // delete file if user clicked 'yes'  
  6.    if (result == MessageBoxResult.Yes)  
  7.    {  
  8.        File.Delete(myFile);  
  9.         extensionCount = Int32.Parse(found["bak"]) - 1;  
  10.        found["bak"] = extensionCount.ToString();  
  12.    } // end if  
  13.  }   
  14. }  
Call the method SearchDirectory for each subdirectory. Using recursion, we ensure that the program performs the same logic for finding the .bak files in each subdirectory. After each subdirectory has been checked for .bak files, the SearchDirectory method completes and displays the results.
  1. // recursive call to search files in subdirectory  
  2. foreach (string myDirectory in directoryList)  
  3. SearchDirectory(myDirectory);  

C# find directory


In the preceding example we learned how to use regular expressions to find directories and determine file type.