Using C# (.NET), how can I search a file system given a directory search mask like this: (?)
\\server\Scanner\images\*Images\*\*_*
For example, I need to first find all top-level directories:
\\server\Scanner\images\Job1Images
\\server\Scanner\images\Job2Images
...then I need to procede further with the search mask:
\\server\Scanner\images\Job1Images\*\*_*
\\server\Scanner\images\Job2Images\*\*_*
This doesn't seem too complicated but I can't figure it out for the life of me...
As mentioned above, I'm using C# and .NET. The search can be trying to locate directories or files. (i.e. *.txt, or <*Directory>)
Like this:
Top Level Directories:
//get Top level
string[] TopLevel = Directory.GetDirectories(path);
And then you will have to do a resursive function of this folders using wildcard pattern,
for example:
// Only get subdirectories that begin with the letter "p."
string pattern = "p*";
string[] dirs = folder.GetDirectories(path, pattern);
I suggest you play with wildcards to get the array output and you will figure out
which is the best way, if using resursive function or directly quering paths.
Edit: Ahh, new functionality with .NET 4 so you don't have to do a recursive function (Thanks Matthew Brubaker)
IEnumerable<String> matchingFilePaths2 = System.IO.Directory.EnumerateFiles(#"C:\some folder to start in", filePatternToMatchOn, System.IO.SearchOption.AllDirectories);
First Answer:
//get all files that have an underscore - searches all folders under the start folder
List<String> matchingFilePaths = new List<string>();
String filePatternToMatchOn = "*_*";
FileUtilities.GetAllFilesMatchingPattern(#"C:\some folder to start in", ref matchingFilePaths, filePatternToMatchOn);
...
public static void GetAllFilesMatchingPattern(String pathToGetFilesIn, ref List<String> fullFilePaths, String searchPattern)
{
//get all files in current directory that match the pattern
String[] filePathsInCurrentDir = Directory.GetFiles(pathToGetFilesIn, searchPattern);
foreach (String fullPath in filePathsInCurrentDir)
{
fullFilePaths.Add(fullPath);
}
//call this method recursively for all directories
String[] directories = Directory.GetDirectories(pathToGetFilesIn);
foreach (String path in directories)
{
GetAllFilesMatchingPattern(path, ref fullFilePaths, searchPattern);
}
}
public static IEnumerable<string> GetImages()
{
//For each "*Image" directory
foreach (var jobFolder in Directory.EnumerateDirectories(#"\\server\Scanner\images", "*Images"))
{
//For each first level subdirectory
foreach (var jobSubFolder in Directory.EnumerateDirectories(jobFolder))
{
//Enumerate each file containing a '_'
foreach (var filePath in Directory.EnumerateFiles(jobSubFolder, "*_*", SearchOption.TopDirectoryOnly))
{
yield return filePath;
}
}
}
}
Only the files from the first level subdirectories of each "*Image" directory are enumerated.
Finally you can use it with:
foreach (var path in GetImages())
{
Console.WriteLine(path);
}
There is a C# procedure where you can search folder by path pattern with wildcards like * and ?.
Example if path pattern C:\Folder?*\Folder2 is passed to the procedru, then a list of folder path will be returned
C:\Folder1\A\Folder2
C:\FolderA\B\Folder2
...
and so on
static List<string> GetFoldersByPathPattern(string folderPathPattern)
{
List<string> directories = new List<string>();
directories.Add("");
string[] folderParts = folderPathPattern.Split(new char[] { '\\' }, StringSplitOptions.None);
foreach (string folderPart in folderParts)
{
if (folderPart.Contains('*') || folderPart.Contains('?'))
{
List<string> newDirectories = new List<string>();
foreach (string directory in directories)
{
foreach (string newDirectory in Directory.GetDirectories(directory, folderPart))
{
newDirectories.Add(newDirectory);
}
}
directories = newDirectories;
}
else
{
for (int i = 0; i < directories.Count(); i++)
{
directories[i] = directories[i] + folderPart + "\\";
}
}
}
return directories;
}
Related
I have a folder path with me something like "c:/videos". it contains subfolders like car, bike, bus ... etc. need to get only the sub folder name and store in a string array.
And please note i don't need a full sub folder path
out needed like:- car, bike, bus
not like c:/videos/car
c:/videos/bike
c:/videos/bus
You have to iterate over the SubDirectories.
And replace the startpath c:\videoswith an empty string:
var rootDir = #"c:\videos";
DirectoryInfo directoryInfo = new DirectoryInfo(rootDir);
var dirs = new System.Collections.Generic.List<string>();
foreach (var dir in directoryInfo.GetDirectories())
{
dirs.Add(dir.Name.Replace($"{rootDir}\\", ""));
}
var result = dirs.ToArray();
You can use GetDirectories method
var directories = Directory.GetDirectories(#"c:/videos");
this will give you a string array of all the subdirectories and then you can call Path.GetDirectoryName() to get the folder name
List<string> subfolders = List<string>();
var directories = Directory.GetDirectories(#"c:/videos");
foreach(var directory in directories)
{
subfolders.Add(Path.GetDirectoryName(directory));
}
var result = subfolders.ToArray();
string yourPath= #"C:\videos";
// Get all subdirectories
string[] subDirs = Directory.GetDirectories(root);
foreach (string subdirectory in subdirectoryEntries)
LoadSubDirs(subdirectory);
List<string> subfolders = List<string>();
private void LoadSubDirs(string dir)
{
subfolders.Add(Path.GetDirectoryName(dir));
string[] subdirectoryEntries = Directory.GetDirectories(dir);
foreach (string subdirectory in subdirectoryEntries)
{
LoadSubDirs(subdirectory);
}
}
How can I search a Path like that in C#:
"C:\MyApp\*\log"
I want to get all Directories that matches that search pattern.
Example result:
C:\MyApp\20171009\log
C:\MyApp\20171008\log
C:\MyApp\20171007\log
In Powershell it works with get-item
Try this iterator-based file functions:
var path = #"C:\temp";
foreach (var file in Directory.EnumerateFiles(path, "*.log", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
For more informations show here
If you are trying to just get the directories with Name Log which match the pattern C:\MyApp*\log, following code should help:
var dirs = Directory.EnumerateDirectories(#"C:\Temp\","log", SearchOption.AllDirectories);
Notice that search pattern is the name of directory and not any file name or file extension
I found a solution for my Problem.
I modified it for Directory-Use.
public static List<string> GetAllMatchingPaths(string pattern)
{
char separator = Path.DirectorySeparatorChar;
string[] parts = pattern.Split(separator);
if (parts[0].Contains('*') || parts[0].Contains('?'))
throw new ArgumentException("path root must not have a wildcard", nameof(parts));
return GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(1)), parts[0]);
}
private static List<string> GetAllMatchingPathsInternal(string pattern, string root)
{
char separator = Path.DirectorySeparatorChar;
string[] parts = pattern.Split(separator);
for (int i = 0; i < parts.Length; i++)
{
// if this part of the path is a wildcard that needs expanding
if (parts[i].Contains('*') || parts[i].Contains('?'))
{
// create an absolute path up to the current wildcard and check if it exists
var combined = root + separator + String.Join(separator.ToString(), parts.Take(i));
if (!Directory.Exists(combined))
return new List<string>();
if (i == parts.Length - 1) // if this is the end of the path (a file name)
{
return ( List<string> ) Directory.EnumerateFiles(combined, parts[i], SearchOption.TopDirectoryOnly);
}
else // if this is in the middle of the path (a directory name)
{
var directories = Directory.EnumerateDirectories(combined, parts[i], SearchOption.TopDirectoryOnly);
List<string> pts = new List<string>();
foreach ( string directory in directories )
{
foreach ( string item in GetAllMatchingPathsInternal(String.Join(separator.ToString(), parts.Skip(i + 1)), directory))
{
pts.Add(item);
}
}
return pts;
}
}
}
I need find the specific file/folder on my hard drive.
For example i need find a file (do1.bat) and then store the path of the file. But i dont know where can it be stored, so i have to scan all hard drive.
How can i use C# for this?
A simple way would be
var results = Directory.GetFiles("c:\\", "do1.bat", SearchOption.AllDirectories);
This would recurse through all directory and collect all files named do1.bat. Unfortunatly this will not work on complete c:\ since it will throw exceptions if you don't have access to a directory, which surely will happen.
So this is a recursive version:
private static void FindFile(DirectoryInfo currentDirectory, string pattern, List<FileInfo> results)
{
try
{
results.AddRange(currentDirectory.GetFiles(pattern, SearchOption.TopDirectoryOnly));
foreach (DirectoryInfo dir in currentDirectory.GetDirectories("*", SearchOption.TopDirectoryOnly).Where(d => d.Name != "." && d.Name != ".."))
FindFile(dir, pattern, results);
}
catch
{
// probably no access to directory
}
}
This recurses through the directory tree and tries to get the files in a directory and then all subdirectories (except . and ..).
You can use it this way:
DirectoryInfo d = new DirectoryInfo("c:\\");
List<FileInfo> results = new List<FileInfo>();
FindFile(d, "do1.bat", results);
This will find all files named do1.bat in any subdirectory of C:\\ and enlist the FileInfos in the results list.
this should provide you a list of files, matching your search pattern
string[] Result = Directory.GetFiles(#"C:\", "do1.bat", SearchOption.AllDirectories);
Refer: https://msdn.microsoft.com/en-us/library/07wt70x2(v=vs.110).aspx
List<string> lstfilepaths = new List<string>();
public static void ProcessDirectory(string targetDirectory)
{
// Process the list of files found in the directory.
string [] fileEntries = Directory.GetFiles(targetDirectory);
foreach(string fileName in fileEntries) // included as per your logic
{
if(fileName == "do1.bat")
{
ProcessFile(fileName);
}
}
// Recurse into subdirectories of this directory.
string [] subdirectoryEntries = Directory.GetDirectories(targetDirectory);
foreach(string subdirectory in subdirectoryEntries)
ProcessDirectory(subdirectory);
}
public static void ProcessFile(string path)
{
lstfilepaths.Add(path);
}
For one file:
public string FindFileByName(string fileName, string searchPath)
{
string resultPath = null;
DirectoryInfo directoryInWhichToSearch = new DirectoryInfo(searchPath);
FileInfo foundFile = directoryInWhichToSearch.GetFiles(fileName, SearchOption.AllDirectories)[0];
resultPath = foundFile.FullName;
return resultPath;
}
You can then use it like this:
string fileFullPath = FindFileByName("do1.bat", #"C:\");
I have a folder that contains sub folders and files with read only attribute (both files and folders). I want to delete this folder with sub-folders and files.
I wrote this code:
static void Main(string[] args)
{
DirectoryInfo mm = new DirectoryInfo(#"c:\ex");
string aa = Convert.ToString(mm);
string[] allFileNames =
System.IO.Directory.GetFiles(aa,
"*.*",
System.IO.SearchOption.AllDirectories);
string[] alldirNames =
System.IO.Directory.GetDirectories(aa,
"*",
System.IO.SearchOption.AllDirectories);
foreach (string filename in allFileNames)
{
FileAttributes attr = File.GetAttributes(filename);
File.SetAttributes(filename, attr & ~FileAttributes.ReadOnly);
}
foreach (string dirname in alldirNames)
{
FileAttributes attr = File.GetAttributes(dirname);
File.SetAttributes(dirname, attr & ~FileAttributes.ReadOnly);
Directory.Delete(dirname , true);
}
FileInfo[] list = mm.GetFiles();
foreach (FileInfo k in list)
{
k.Delete();
}
mm.Delete();
Console.ReadKey();
}
The problem now is that whenever I run the program it gives me the following error:
Could not find a part of the path 'c:\ex\xx\bb'.
What does this error mean?
Directory.Delete(path, true);
Documentation
The previous answer might work, but I believe it will occur with problems in ReadOnly files. But to ensure the deletion and removal of any attribute ReadOnly, the best way to perform this procedure you must be using a method to facilitate the way you were doing, you were not using the correct properties of objects, for example, when using
DirectoryInfo.ToString ()
and use the
DirectoryInfo.GetFiles (aa ...
you were not using the resources the Framework offers within the DirectoryInfo class. See below:
void DirectoryDelete(string strOriginalPath)
{
DirectoryInfo diOriginalPath = new DirectoryInfo(strOriginalPath);
if (diOriginalPath.Attributes.HasFlag(FileAttributes.ReadOnly))
diOriginalPath.Attributes &= ~FileAttributes.ReadOnly;
string[] lstFileList = Directory.GetFiles(strOriginalPath);
string[] lstdirectoryList = Directory.GetDirectories(strOriginalPath);
if (lstdirectoryList.Length > 0)
{
// foreach on the subdirs to the call method recursively
foreach (string strSubDir in lstdirectoryList)
DirectoryDelete(strSubDir);
}
if (lstFileList.Length > 0)
{
// foreach in FileList to be delete files
foreach (FileInfo fiFileInDir in lstFileList.Select(strArquivo => new FileInfo(strArquivo)))
{
// removes the ReadOnly attribute
if (fiFileInDir.IsReadOnly)
fiFileInDir.Attributes &= ~FileAttributes.ReadOnly;
// Deleting file
fiFileInDir.Delete();
}
}
diOriginalPath.Delete();
}
EmptyFolder(new DirectoryInfo(#"C:\your Path"))
Directory.Delete(#"C:\your Path");
private void EmptyFolder(DirectoryInfo directoryInfo)
{
foreach (FileInfo file in directoryInfo.GetFiles())
{
file.Delete();
}
foreach (DirectoryInfo subfolder in directoryInfo.GetDirectories())
{
EmptyFolder(subfolder);
}
}
Well I like this nice piece of code right here it seems to work awesomely but I can't seem to add any more directories to it
DirectoryInfo dir = new DirectoryInfo(#"C:\temp");
foreach(FileInfo files in dir.GetFiles())
{
files.Delete();
}
foreach (DirectoryInfo dirs in dir.GetDirectories())
{
dirs.Delete(true);
}
I would also like to add in special folders as well like History and cookies and such how would I go about doing that (I would like to include at least 4-5 different folders)
Perhaps something like this would help. I did not test it.
public void DeleteDirectoryFolders(DirectoryInfo dirInfo){
foreach (DirectoryInfo dirs in dirInfo.GetDirectories())
{
dirs.Delete(true);
}
}
public void DeleteDirectoryFiles(DirectoryInfo dirInfo) {
foreach(FileInfo files in dirInfo.GetFiles())
{
files.Delete();
}
}
public void DeleteDirectoryFilesAndFolders(string dirName) {
DirectoryInfo dir = new DirectoryInfo(dirName);
DeleteDirectoryFiles(dir)
DeleteDirectoryFolders(dir)
}
public void main() {
List<string> DirectoriesToDelete;
DirectoriesToDelete.add("c:\temp");
DirectoriesToDelete.add("c:\temp1");
DirectoriesToDelete.add("c:\temp2");
DirectoriesToDelete.add("c:\temp3");
foreach (string dirName in DirectoriesToDelete) {
DeleteDirectoryFilesAndFolders(dirName);
}
}
Here's a recursive function that will delete all files in a given directory and navigate down the directory structure. A pattern string can be supplied to only work with files of a given extension, as per your comment to another answer.
Action<string,string> fileDeleter = null;
fileDeleter = (directoryPath, pattern) =>
{
string[] files;
if (!string.IsNullOrEmpty(pattern))
files = Directory.GetFiles(directoryPath, pattern);
else
files = Directory.GetFiles(directoryPath);
foreach (string file in files)
{
File.Delete(file);
}
string[] directories = Directory.GetDirectories(directoryPath);
foreach (string dir in directories)
fileDeleter(dir, pattern);
};
string path = #"C:\some_folder\";
fileDeleter(path, "*.bmp");
Directories are otherwise left alone, and this can obviously be used with an array or list of strings to work with multiple initial directory paths.
Here is the same code rewritten as a standard function, also with the recursion as a parameter option.
public void DeleteFilesFromDirectory(string directoryPath, string pattern, bool includeSubdirectories)
{
string[] files;
if (!string.IsNullOrEmpty(pattern))
files = Directory.GetFiles(directoryPath, pattern);
else
files = Directory.GetFiles(directoryPath);
foreach (string file in files)
{
File.Delete(file);
}
if (includeSubdirectories)
{
string[] directories = Directory.GetDirectories(directoryPath);
foreach (string dir in directories)
DeleteFilesFromDirectory(dir, pattern, includeSubdirectories);
}
}