Find the difference of two folders and delete files - c#

I have two folders : FolderA and FolderB
I want to delete the files in FolderA which also exist in FolderB. (i.e. Common files will be deleted from folderA)
How can I do this most efficiently in C#? (That's a critical point in the project and it has to be as efficient as possible )
Thanx

This is easy, readable and also efficient:
var common = from f1 in Directory.EnumerateFiles(folderA, "*.*", SearchOption.AllDirectories)
join f2 in Directory.EnumerateFiles(folderB, "*.*", SearchOption.AllDirectories)
on Path.GetFileName(f1) equals Path.GetFileName(f2)
select f1;
foreach (string file in common)
{
File.Delete(file);
}
Assuming that you just want to compare the file names (and extension).

You can do this with the help of LINQ. See here.

If you only want to compare file names, here is how you can do it, I did a quick test of this code and it works:
string pathA = #"C:\New FolderA";
string pathB = #"C:\New FolderB";
var filesA = Directory.GetFiles(pathA).Select(path => Path.GetFileName(path));
var filesB = Directory.GetFiles(pathB).Select(path => Path.GetFileName(path));
var toBeDeleted = filesA.Intersect(filesB);
foreach (string filename in toBeDeleted)
File.Delete(Path.Combine(pathA, filename));

string[] FolderAFiles = Directory.GetFiles(#"Path");
string[] FolderBFiles = Directory.GetFiles(#"BPath");
foreach (string Files in FolderAFiles)
{
if (FolderBFiles.Contains(Files))
{
File.Delete(Files);
}
}
Try this

Here's one another solution.
var filesInB = System.IO.Directory.GetFiles("FolderB");
Array.ForEach(System.IO.Directory.GetFiles("FolderA"), delegate(string fileName){
if (filesInB.Contains(fileName)) System.IO.File.Delete(fileName);
});

Related

Searching with System.IO.Directory.GetFiles and wildcards in path

I have a curious problem in a C#-program.
I have some local folderpaths like
"C:\test\AB_Systems\ELEGANCE\CB-DOC\live\M7-091.249.99.XX.01\extobjects".
Now i want to search for PDF-files in the subfolder called "extobjects".
Unfortunately there are many subfolders in the folder "live", which got a subfolder called "extobjects", so i thought it would be better to use a wildcard in the searchpath like that:
"C:\test\AB_Systems\ELEGANCE\CB-DOC\live\*\extobjects"
But this doesn't work.
Is there a way do do this?
public static FileInfo[] findFile(String whereToSearch, String searchFor , String mode)
{
IEnumerable<FileInfo> files = null;
if (mode.Equals(""))
mode = "s";
if (searchFor.Equals(""))
searchFor = "*";
if (mode.Equals("r") || mode.Equals("recursive"))
{
DirectoryInfo dir = new DirectoryInfo(whereToSearch);
files = dir.EnumerateFiles(searchFor, searchOption: SearchOption.AllDirectories);
}
if (mode.Equals("s") || mode.Equals("specific"))
{
DirectoryInfo dir = new DirectoryInfo(whereToSearch);
files = dir.EnumerateFiles(searchFor, searchOption: SearchOption.TopDirectoryOnly);
}
if (files != null) return files.ToArray<FileInfo>();
else return null;
}
That's an example how to do it.
It's important to say that only the filename can contain a wildcard pattern like *. The Path can be given as where to start the search and by giving searchOption: searchOption.AllDirectories as an argument it will go through all sub-directories of the entry path.
You will receive an Array of FileInfo which objects that contain the the path and more information.
You can use Linq like this:
var files = Directory
.EnumerateDirectories(#"C:\test\AB_Systems\ELEGANCE\CB-DOC\live", "extobjects", SearchOption.AllDirectories)
.SelectMany(x => Directory.EnumerateFiles(x, "*pdf", SearchOption.TopDirectoryOnly))
.ToArray();
I'd choose a solution exactly what BugFinder proposed, you could optimize the following foreach-loop into a LINQ query if your .NET target supports it.
// Itterate subdirectories of the live folder
foreach (var subDir in Directory.GetDirectories(#"C:\test\AB_Systems\ELEGANCE\CB-DOC\live"))
{
// Check if path to extobjects exists
var extObjects = Path.Combine(subDir, "extobjects");
if (Directory.Exists(extObjects))
{
var pdfFiles = Directory.GetFiles(extObjects, "*").Where(x=>x.EndsWith(".pdf"));
// Do something with the pdf file paths
}
}

how to compare filenames, then classify uniquely from folder into ListBox if repeated

I have json files that i'm trying to classify so the file names are as such:
inputTestingSetting_test
inputTestingSetting_test1310
inputTestingSetting_test1310_ckf
inputTestingSetting_test1310_ols
inputTestingSetting_test1310_sum
inputTestingSetting_test1311_ckf
inputTestingSetting_test1311_ols
inputTestingSetting_test1311_sum
So the output that i want in the ListBox lbJsonFileNames will be
test
test1310
test1311
currently my codes are
DirectoryInfo dInfo = new DirectoryInfo(tbJSFolder.Text);
FileInfo[] Files = dInfo.GetFiles("*.json");
List<jSonName> jsonName = new List<jSonName>();
foreach (FileInfo file in Files)
{
string filename = Path.GetFileNameWithoutExtension(file.Name);
string[] fileNameSplit = filename.Split('_');
jsonName = new List<jSonName>{
new jSonName(fileNameSplit[0],fileNameSplit[1])
};
for(int i=0;i<jsonName.Count;i++)
{
if(jsonName[i].TestNumber == fileNameSplit[1])
{
lbJsonFileNames.Items.Add(jsonName[i].TestNumber);
}
}
}
so my output for lbJsonFileNames is what i want, however it is repeated. is it possible to just show one? i've tried to put jsonName[i].TestNumber to jsonName[i+1].TestNumber. but failed as it is out of range.
is there a way to read the file names, and then compare it with the previous file name to see if it is the same? and if it is the same, ignore, move on to the next file name, if it's different then it is added into the ListBox
changed my codes to
DirectoryInfo dInfo = new DirectoryInfo(tbJSFolder.Text);
FileInfo[] Files = dInfo.GetFiles("*.json");
List<jSonName> jsonName = new List<jSonName>();
HashSet<string> fileNames = new HashSet<string>();
foreach (FileInfo file in Files)
{
string filename = Path.GetFileNameWithoutExtension(file.Name);
string[] fileNameSplit = filename.Split('_');
fileNames.Add(fileNameSplit[1]);
}
foreach(var value in fileNames)
{
lbJsonFileNames.Items.Add(value);
}
got what i want now thanks all~
Your code basically says to put the following into list box:
test
test1310
test1310
test1310
test1310
test1311
test1311
test1311
Before you add as in lbJsonFileNames.Items.Add(jsonName[i].TestNumber);, check for duplicate first. Maybe you can put that list into a Set variable. Set will automatically remove the duplicate. Then put the Set back to lbJsonFileNames.
[Edit] Sorry there is no Set in dot net. Please use HashSet instead.[/Edit]
Your code did not mention what jSonName class is like and the constructor parameters stand for. However to get your output from your input can be much easier:
string[] all = Directory.GetFiles(tbJSFolder.Text, "*.json")
.Select(x => Path.GetFileNameWithoutExtension(x))
.Select(x => x.Split(new char[] { '_' })[1])
.Distinct().ToArray();
lbJsonFileNames.Items.AddRange(all);

How to delete back up files

I need to delete files with ".bak" and ".csv.bak" extensions. I use .net c#.
I tried like this:
string srcDir = #"D:\Backup";
string[] bakList = Directory.GetFiles(srcDir,".bak");
if (Directory.Exists(srcDir))
{
foreach (string f in bakList)
{
File.Delete(f);
}
}
But when debugging, the bakList array is empty.
Directory.GetFiles() is not loading the file names in the array. I cant figure out what is wrong in my coding.
You need to Add * before your .bak in GetFiles()
string srcDir = #"D:\Backup";
string[] bakList = Directory.GetFiles(srcDir,"*.bak");
if (Directory.Exists(srcDir))
{
foreach (string f in bakList)
{
File.Delete(f);
}
}
If you need to search for both types maybe it works better
var files = Directory.GetFiles(srcDir, "*.*")
.Where(s => s.EndsWith(".bak"));
If your file name is
"Data Logger[2].csv.bak",
go to the properties and check the type of file. it will be something like this
"1 File (.1)" .The file has number as its end extension. So i used like this.
string[] bk = Directory.GetFiles(srcDir, "*.bak.*");
foreach (string f in bk)
{
File.Delete(f);
}
its working...

How to check for file names in a folder

I would like to be able to iterate through the name of some image files in a folder using c#. So for intance I have a folder named image and contains the following images
image
dog.jpg
cat.jpg
horse.jpg
I want to be able to go through the names and be able to say
if(filename == dog.jpg)
return true
else
return false
Something of that nature
Thank you
You should use the static Exists method on System.IO.File.
return System.IO.File.Exists("dog.jpg")
Since the method returns a boolean, there is no need for the if statement in the example you gave.
You can also use a bit of Linq magic to determine if a file exists in a folder structure, like this:
var dir = new System.IO.DirectoryInfo(startFolder);
var fileList = dir.GetFiles("*.*", System.IO.SearchOption.AllDirectories);
bool fileExists = fileList.Any(f => f.FullName == "dog.jpg");
or even shorter:
return System.IO.Directory
.GetFiles(#"c:\myfolder", "dog.jpg", SearchOption.AllDirectories)
.Any();
which would search the folder specified and all subfolder with the pattern "dog.jpg". The Any() extension method simply checks whether the IEnumerable contains any items. I think this is the most efficient way of doing this (based on gut feeling).
From http://weblogs.asp.net/israelio/archive/2004/06/23/162913.aspx Just insert your if in the "// do something with filename" area:
// 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);
}
}
get all the files
string[] filePaths = Directory.GetFiles(#"c:\yourfolder\");
and iterate through it
use Directory.GetFiles()
foreach(var file in (myDir.GetFiles("*.jpg")
{
if(file.Name == "dog.jpg") return true;
}
var files = System.IO.Directory.GetFiles("directory", "*.jpg");
foreach (var item in files)
{
if (System.IO.Path.GetFileName(item) == "dog.jpg")
{
// File found.
}
}
DirectoryInfo di = new DirectoryInfo("c:\\Images");
var files = di.GetFiles("*.jpg");
foreach (var fileInfo in files)
{
if (fileInfo.Name == "dog.jpg")
return true;
}
return false;

Can you call Directory.GetFiles() with multiple filters?

I am trying to use the Directory.GetFiles() method to retrieve a list of files of multiple types, such as mp3's and jpg's. I have tried both of the following with no luck:
Directory.GetFiles("C:\\path", "*.mp3|*.jpg", SearchOption.AllDirectories);
Directory.GetFiles("C:\\path", "*.mp3;*.jpg", SearchOption.AllDirectories);
Is there a way to do this in one call?
For .NET 4.0 and later,
var files = Directory.EnumerateFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
For earlier versions of .NET,
var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".mp3") || s.EndsWith(".jpg"));
edit: Please read the comments. The improvement that Paul Farry suggests, and the memory/performance issue that Christian.K points out are both very important.
How about this:
private static string[] GetFiles(string sourceFolder, string filters, System.IO.SearchOption searchOption)
{
return filters.Split('|').SelectMany(filter => System.IO.Directory.GetFiles(sourceFolder, filter, searchOption)).ToArray();
}
I found it here (in the comments): http://msdn.microsoft.com/en-us/library/wz42302f.aspx
If you have a large list of extensions to check you can use the following. I didn't want to create a lot of OR statements so i modified what lette wrote.
string supportedExtensions = "*.jpg,*.gif,*.png,*.bmp,*.jpe,*.jpeg,*.wmf,*.emf,*.xbm,*.ico,*.eps,*.tif,*.tiff,*.g01,*.g02,*.g03,*.g04,*.g05,*.g06,*.g07,*.g08";
foreach (string imageFile in Directory.GetFiles(_tempDirectory, "*.*", SearchOption.AllDirectories).Where(s => supportedExtensions.Contains(Path.GetExtension(s).ToLower())))
{
//do work here
}
for
var exts = new[] { "mp3", "jpg" };
You could:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
Directory
.EnumerateFiles(path, "*.*")
.Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
Don't forget the new .NET4 Directory.EnumerateFiles for a performance boost (What is the difference between Directory.EnumerateFiles vs Directory.GetFiles?)
"IgnoreCase" should be faster than "ToLower" (.EndsWith("aspx", StringComparison.OrdinalIgnoreCase) rather than .ToLower().EndsWith("aspx"))
But the real benefit of EnumerateFiles shows up when you split up the filters and merge the results:
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
exts.Select(x => "*." + x) // turn into globs
.SelectMany(x =>
Directory.EnumerateFiles(path, x)
);
}
It gets a bit faster if you don't have to turn them into globs (i.e. exts = new[] {"*.mp3", "*.jpg"} already).
Performance evaluation based on the following LinqPad test (note: Perf just repeats the delegate 10000 times)
https://gist.github.com/zaus/7454021
( reposted and extended from 'duplicate' since that question specifically requested no LINQ: Multiple file-extensions searchPattern for System.IO.Directory.GetFiles )
I know it's old question but LINQ: (.NET40+)
var files = Directory.GetFiles("path_to_files").Where(file => Regex.IsMatch(file, #"^.+\.(wav|mp3|txt)$"));
There is also a descent solution which seems not to have any memory or performance overhead and be quite elegant:
string[] filters = new[]{"*.jpg", "*.png", "*.gif"};
string[] filePaths = filters.SelectMany(f => Directory.GetFiles(basePath, f)).ToArray();
Another way to use Linq, but without having to return everything and filter on that in memory.
var files = Directory.GetFiles("C:\\path", "*.mp3", SearchOption.AllDirectories).Union(Directory.GetFiles("C:\\path", "*.jpg", SearchOption.AllDirectories));
It's actually 2 calls to GetFiles(), but I think it's consistent with the spirit of the question and returns them in one enumerable.
Let
var set = new HashSet<string>(
new[] { ".mp3", ".jpg" },
StringComparer.OrdinalIgnoreCase); // ignore case
var dir = new DirectoryInfo(path);
Then
dir.EnumerateFiles("*.*", SearchOption.AllDirectories)
.Where(f => set.Contains(f.Extension));
or
from file in dir.EnumerateFiles("*.*", SearchOption.AllDirectories)
from ext in set // makes sense only if it's just IEnumerable<string> or similar
where String.Equals(ext, file.Extension, StringComparison.OrdinalIgnoreCase)
select file;
Nope. Try the following:
List<string> _searchPatternList = new List<string>();
...
List<string> fileList = new List<string>();
foreach ( string ext in _searchPatternList )
{
foreach ( string subFile in Directory.GetFiles( folderName, ext )
{
fileList.Add( subFile );
}
}
// Sort alpabetically
fileList.Sort();
// Add files to the file browser control
foreach ( string fileName in fileList )
{
...;
}
Taken from: http://blogs.msdn.com/markda/archive/2006/04/20/580075.aspx
I can't use .Where method because I'm programming in .NET Framework 2.0 (Linq is only supported in .NET Framework 3.5+).
Code below is not case sensitive (so .CaB or .cab will be listed too).
string[] ext = new string[2] { "*.CAB", "*.MSU" };
foreach (string found in ext)
{
string[] extracted = Directory.GetFiles("C:\\test", found, System.IO.SearchOption.AllDirectories);
foreach (string file in extracted)
{
Console.WriteLine(file);
}
}
List<string> FileList = new List<string>();
DirectoryInfo di = new DirectoryInfo("C:\\DirName");
IEnumerable<FileInfo> fileList = di.GetFiles("*.*");
//Create the query
IEnumerable<FileInfo> fileQuery = from file in fileList
where (file.Extension.ToLower() == ".jpg" || file.Extension.ToLower() == ".png")
orderby file.LastWriteTime
select file;
foreach (System.IO.FileInfo fi in fileQuery)
{
fi.Attributes = FileAttributes.Normal;
FileList.Add(fi.FullName);
}
in .NET 2.0 (no Linq):
public static List<string> GetFilez(string path, System.IO.SearchOption opt, params string[] patterns)
{
List<string> filez = new List<string>();
foreach (string pattern in patterns)
{
filez.AddRange(
System.IO.Directory.GetFiles(path, pattern, opt)
);
}
// filez.Sort(); // Optional
return filez; // Optional: .ToArray()
}
Then use it:
foreach (string fn in GetFilez(path
, System.IO.SearchOption.AllDirectories
, "*.xml", "*.xml.rels", "*.rels"))
{}
DirectoryInfo directory = new DirectoryInfo(Server.MapPath("~/Contents/"));
//Using Union
FileInfo[] files = directory.GetFiles("*.xlsx")
.Union(directory
.GetFiles("*.csv"))
.ToArray();
If you are using VB.NET (or imported the dependency into your C# project), there actually exists a convenience method that allows to filter for multiple extensions:
Microsoft.VisualBasic.FileIO.FileSystem.GetFiles("C:\\path", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, new string[] {"*.mp3", "*.jpg"});
In VB.NET this can be accessed through the My-namespace:
My.Computer.FileSystem.GetFiles("C:\path", FileIO.SearchOption.SearchAllSubDirectories, {"*.mp3", "*.jpg"})
Unfortunately, these convenience methods don't support a lazily evaluated variant like Directory.EnumerateFiles() does.
The following function searches on multiple patterns, separated by commas. You can also specify an exclusion, eg: "!web.config" will search for all files and exclude "web.config". Patterns can be mixed.
private string[] FindFiles(string directory, string filters, SearchOption searchOption)
{
if (!Directory.Exists(directory)) return new string[] { };
var include = (from filter in filters.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries) where !string.IsNullOrEmpty(filter.Trim()) select filter.Trim());
var exclude = (from filter in include where filter.Contains(#"!") select filter);
include = include.Except(exclude);
if (include.Count() == 0) include = new string[] { "*" };
var rxfilters = from filter in exclude select string.Format("^{0}$", filter.Replace("!", "").Replace(".", #"\.").Replace("*", ".*").Replace("?", "."));
Regex regex = new Regex(string.Join("|", rxfilters.ToArray()));
List<Thread> workers = new List<Thread>();
List<string> files = new List<string>();
foreach (string filter in include)
{
Thread worker = new Thread(
new ThreadStart(
delegate
{
string[] allfiles = Directory.GetFiles(directory, filter, searchOption);
if (exclude.Count() > 0)
{
lock (files)
files.AddRange(allfiles.Where(p => !regex.Match(p).Success));
}
else
{
lock (files)
files.AddRange(allfiles);
}
}
));
workers.Add(worker);
worker.Start();
}
foreach (Thread worker in workers)
{
worker.Join();
}
return files.ToArray();
}
Usage:
foreach (string file in FindFiles(#"D:\628.2.11", #"!*.config, !*.js", SearchOption.AllDirectories))
{
Console.WriteLine(file);
}
What about
string[] filesPNG = Directory.GetFiles(path, "*.png");
string[] filesJPG = Directory.GetFiles(path, "*.jpg");
string[] filesJPEG = Directory.GetFiles(path, "*.jpeg");
int totalArraySizeAll = filesPNG.Length + filesJPG.Length + filesJPEG.Length;
List<string> filesAll = new List<string>(totalArraySizeAll);
filesAll.AddRange(filesPNG);
filesAll.AddRange(filesJPG);
filesAll.AddRange(filesJPEG);
Just found an another way to do it. Still not one operation, but throwing it out to see what other people think about it.
private void getFiles(string path)
{
foreach (string s in Array.FindAll(Directory.GetFiles(path, "*", SearchOption.AllDirectories), predicate_FileMatch))
{
Debug.Print(s);
}
}
private bool predicate_FileMatch(string fileName)
{
if (fileName.EndsWith(".mp3"))
return true;
if (fileName.EndsWith(".jpg"))
return true;
return false;
}
I wonder why there are so many "solutions" posted?
If my rookie-understanding on how GetFiles works is right, there are only two options and any of the solutions above can be brought down to these:
GetFiles, then filter: Fast, but a memory killer due to storing overhead untill the filters are applied
Filter while GetFiles: Slower the more filters are set, but low memory usage as no overhead is stored.This is explained in one of the above posts with an impressive benchmark: Each filter option causes a seperate GetFile-operation so the same part of the harddrive gets read several times.
In my opinion Option 1) is better, but using the SearchOption.AllDirectories on folders like C:\ would use huge amounts of memory.
Therefor i would just make a recursive sub-method that goes through all subfolders using option 1)
This should cause only 1 GetFiles-operation on each folder and therefor be fast (Option 1), but use only a small amount of memory as the filters are applied afters each subfolders' reading -> overhead is deleted after each subfolder.
Please correct me if I am wrong. I am as i said quite new to programming but want to gain deeper understanding of things to eventually become good at this :)
Here is a simple and elegant way of getting filtered files
var allowedFileExtensions = ".csv,.txt";
var files = Directory.EnumerateFiles(#"C:\MyFolder", "*.*", SearchOption.TopDirectoryOnly)
.Where(s => allowedFileExtensions.IndexOf(Path.GetExtension(s)) > -1).ToArray();
Make the extensions you want one string i.e ".mp3.jpg.wma.wmf" and then check if each file contains the extension you want.
This works with .net 2.0 as it does not use LINQ.
string myExtensions=".jpg.mp3";
string[] files=System.IO.Directory.GetFiles("C:\myfolder");
foreach(string file in files)
{
if(myExtensions.ToLower().contains(System.IO.Path.GetExtension(s).ToLower()))
{
//this file has passed, do something with this file
}
}
The advantage with this approach is you can add or remove extensions without editing the code i.e to add png images, just write myExtensions=".jpg.mp3.png".
/// <summary>
/// Returns the names of files in a specified directories that match the specified patterns using LINQ
/// </summary>
/// <param name="srcDirs">The directories to seach</param>
/// <param name="searchPatterns">the list of search patterns</param>
/// <param name="searchOption"></param>
/// <returns>The list of files that match the specified pattern</returns>
public static string[] GetFilesUsingLINQ(string[] srcDirs,
string[] searchPatterns,
SearchOption searchOption = SearchOption.AllDirectories)
{
var r = from dir in srcDirs
from searchPattern in searchPatterns
from f in Directory.GetFiles(dir, searchPattern, searchOption)
select f;
return r.ToArray();
}
Nop... I believe you have to make as many calls as the file types you want.
I would create a function myself taking an array on strings with the extensions I need and then iterate on that array making all the necessary calls. That function would return a generic list of the files matching the extensions I'd sent.
Hope it helps.
I had the same problem and couldn't find the right solution so I wrote a function called GetFiles:
/// <summary>
/// Get all files with a specific extension
/// </summary>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>array of all the files with the specific extensions</returns>
public string[] GetFiles(List<string> extensionsToCompare, string Location)
{
List<string> files = new List<string>();
foreach (string file in Directory.GetFiles(Location))
{
if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.')+1).ToLower())) files.Add(file);
}
files.Sort();
return files.ToArray();
}
This function will call Directory.Getfiles() only one time.
For example call the function like this:
string[] images = GetFiles(new List<string>{"jpg", "png", "gif"}, "imageFolder");
EDIT: To get one file with multiple extensions use this one:
/// <summary>
/// Get the file with a specific name and extension
/// </summary>
/// <param name="filename">the name of the file to find</param>
/// <param name="extensionsToCompare">string list of all the extensions</param>
/// <param name="Location">string of the location</param>
/// <returns>file with the requested filename</returns>
public string GetFile( string filename, List<string> extensionsToCompare, string Location)
{
foreach (string file in Directory.GetFiles(Location))
{
if (extensionsToCompare.Contains(file.Substring(file.IndexOf('.') + 1).ToLower()) &&& file.Substring(Location.Length + 1, (file.IndexOf('.') - (Location.Length + 1))).ToLower() == filename)
return file;
}
return "";
}
For example call the function like this:
string image = GetFile("imagename", new List<string>{"jpg", "png", "gif"}, "imageFolder");
Using GetFiles search pattern for filtering the extension is not safe!!
For instance you have two file Test1.xls and Test2.xlsx and you want to filter out xls file using search pattern *.xls, but GetFiles return both Test1.xls and Test2.xlsx
I was not aware of this and got error in production environment when some temporary files suddenly was handled as right files. Search pattern was *.txt and temp files was named *.txt20181028_100753898
So search pattern can not be trusted, you have to add extra check on filenames as well.
Or you can just convert the string of extensions to String^
vector <string> extensions = { "*.mp4", "*.avi", "*.flv" };
for (int i = 0; i < extensions.size(); ++i)
{
String^ ext = gcnew String(extensions[i].c_str());;
String^ path = "C:\\Users\\Eric\\Videos";
array<String^>^files = Directory::GetFiles(path,ext);
Console::WriteLine(ext);
cout << " " << (files->Length) << endl;
}
i don t know what solution is better, but i use this:
String[] ext = "*.ext1|*.ext2".Split('|');
List<String> files = new List<String>();
foreach (String tmp in ext)
{
files.AddRange(Directory.GetFiles(dir, tmp, SearchOption.AllDirectories));
}
you can add this to your project
public static class Collectables {
public static List<System.IO.FileInfo> FilesViaPattern(this System.IO.DirectoryInfo fldr, string pattern) {
var filter = pattern.Split(" ");
return fldr.GetFiles( "*.*", System.IO.SearchOption.AllDirectories)
.Where(l => filter.Any(k => l.Name.EndsWith(k))).ToList();
}
}
then use it anywhere like this
new System.IO.DirectoryInfo("c:\\test").FilesViaPattern("txt doc any.extension");

Categories