This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Can you call Directory.GetFiles() with multiple filters?
How do you filter on more than one extension?
I've tried:
FileInfo[] Files = dinfo.GetFiles("*.jpg;*.tiff;*.bmp");
FileInfo[] Files = dinfo.GetFiles("*.jpg,*.tiff,*.bmp");
Why not create an extension method? That's more readable.
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions)
{
if (extensions == null)
throw new ArgumentNullException("extensions");
IEnumerable<FileInfo> files = Enumerable.Empty<FileInfo>();
foreach(string ext in extensions)
{
files = files.Concat(dir.GetFiles(ext));
}
return files;
}
EDIT: a more efficient version:
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dir, params string[] extensions)
{
if (extensions == null)
throw new ArgumentNullException("extensions");
IEnumerable<FileInfo> files = dir.EnumerateFiles();
return files.Where(f => extensions.Contains(f.Extension));
}
Usage:
DirectoryInfo dInfo = new DirectoryInfo(#"c:\MyDir");
dInfo.GetFilesByExtensions(".jpg",".exe",".gif");
You can get every file, then filter the array:
public static IEnumerable<FileInfo> GetFilesByExtensions(this DirectoryInfo dirInfo, params string[] extensions)
{
var allowedExtensions = new HashSet<string>(extensions, StringComparer.OrdinalIgnoreCase);
return dirInfo.EnumerateFiles()
.Where(f => allowedExtensions.Contains(f.Extension));
}
This will be (marginally) faster than every other answer here.
In .Net 3.5, replace EnumerateFiles with GetFiles (which is slower).
And use it like this:
var files = new DirectoryInfo(...).GetFilesByExtensions(".jpg", ".mov", ".gif", ".mp4");
You can't do that, because GetFiles only accepts a single search pattern. Instead, you can call GetFiles with no pattern, and filter the results in code:
string[] extensions = new[] { ".jpg", ".tiff", ".bmp" };
FileInfo[] files =
dinfo.GetFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();
If you're working with .NET 4, you can use the EnumerateFiles method to avoid loading all FileInfo objects in memory at once:
string[] extensions = new[] { ".jpg", ".tiff", ".bmp" };
FileInfo[] files =
dinfo.EnumerateFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();
You can use LINQ Union method:
dir.GetFiles("*.txt").Union(dir.GetFiles("*.jpg")).ToArray();
The following retrieves the jpg, tiff and bmp files and gives you an IEnumerable<FileInfo> over which you can iterate:
var files = dinfo.GetFiles("*.jpg")
.Concat(dinfo.GetFiles("*.tiff"))
.Concat(dinfo.GetFiles("*.bmp"));
If you really need an array, simply stick .ToArray() at the end of this.
I'm not sure if that is possible. The MSDN GetFiles reference says a search pattern, not a list of search patterns.
I might be inclined to fetch each list separately and "foreach" them into a final list.
I know there is a more elegant way to do this and I'm open to suggestions... this is what I did:
try
{
// Set directory for list to be made of
DirectoryInfo jpegInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo jpgInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo gifInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo tiffInfo = new DirectoryInfo(destinationFolder);
DirectoryInfo bmpInfo = new DirectoryInfo(destinationFolder);
// Set file type
FileInfo[] Jpegs = jpegInfo.GetFiles("*.jpeg");
FileInfo[] Jpgs = jpegInfo.GetFiles("*.jpg");
FileInfo[] Gifs = gifInfo.GetFiles("*.gif");
FileInfo[] Tiffs = gifInfo.GetFiles("*.tiff");
FileInfo[] Bmps = gifInfo.GetFiles("*.bmp");
// listBox1.Items.Add(#""); // Hack for the first list item no preview problem
// Iterate through each file, displaying only the name inside the listbox...
foreach (FileInfo file in Jpegs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Jpgs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Gifs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Tiffs)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
foreach (FileInfo file in Bmps)
{
listBox1.Items.Add(file.Name);
Photo curPhoto = new Photo();
curPhoto.PhotoLocation = file.FullName;
metaData.AddPhoto(curPhoto);
}
Related
I am trying to make a program to backup files from a particular folder, along with the files within the subfolders of the main folder to another backup folder.
This is part of the code I am trying to accomplish the goal, however I am getting backed up only the files from the main folder, and the subfolders are being copied entirely(all of the files in them).
public static string[] Backup(string sourceDirectory, string targetDirectory, string backupDirectory)
{
DirectoryInfo diBackup = new DirectoryInfo(backupDirectory);
DirectoryInfo diTarget = new DirectoryInfo(targetDirectory);
List<string> dups = new List<string>();
string[] fileNamesSource = Directory.GetFiles(sourceDirectory, "*", SearchOption.AllDirectories);
string[] fileNamesDest = Directory.GetFiles(targetDirectory, "*", SearchOption.AllDirectories);
List<string> dupNS = new List<string>();
List<string> dupND = new List<string>();
List<string> BCKP = new List<string>();
string replacement = "";
for (int i = 0; i < fileNamesDest.Length; i++)
{
string res = fileNamesDest[i].Replace(targetDirectory, replacement);
dupND.Add(res);
}
foreach (var ns in fileNamesSource)
{
string res = ns.Replace(sourceDirectory, replacement);
dupNS.Add(res);
}
var duplicates = dupND.Intersect(dupNS);
string[] DuplicatesStringArray = duplicates.ToArray();
foreach (var dup in DuplicatesStringArray)
{
string res = targetDirectory + dup;
BCKP.Add(res);
}
string[] ToBeBackedUp = BCKP.ToArray();
Directory.CreateDirectory(diBackup.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in diTarget.GetFiles())
{
if (ToBeBackedUp.Contains(fi.FullName)){
fi.CopyTo(Path.Combine(diBackup.FullName, fi.Name), true);
}
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in diTarget.GetDirectories())
{
if (ToBeBackedUp.Contains(diSourceSubDir.FullName)) {
DirectoryInfo nextTargetSubDir =
diBackup.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
return ToBeBackedUp;
}
Any ideas of how can I copy only the files in the subfolders that exist in the "source" folder?
Also the CopyAll function:
public static void CopyAll(DirectoryInfo source, DirectoryInfo target)
{
Directory.CreateDirectory(target.FullName);
// Copy each file into the new directory.
foreach (FileInfo fi in source.GetFiles())
{
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
// Copy each subdirectory using recursion.
foreach (DirectoryInfo diSourceSubDir in source.GetDirectories())
{
DirectoryInfo nextTargetSubDir =
target.CreateSubdirectory(diSourceSubDir.Name);
CopyAll(diSourceSubDir, nextTargetSubDir);
}
}
Thanks in advance.
You can try this way as
Much easier
//Now Create all of the directories
foreach (string dirPath in Directory.GetDirectories(SourcePath, "*",
SearchOption.AllDirectories))
Directory.CreateDirectory(dirPath.Replace(SourcePath, DestinationPath));
//Copy all the files & Replaces any files with the same name
foreach (string newPath in Directory.GetFiles(SourcePath, "*.*",
SearchOption.AllDirectories))
File.Copy(newPath, newPath.Replace(SourcePath, DestinationPath), true);
A simple solution: in your CopyAll method, load the SearchOption.AllDirectories argument to your GetFiles method:
foreach (FileInfo fi in source.GetFiles("*", SearchOption.AllDirectories))
{
fi.CopyTo(Path.Combine(target.FullName, fi.Name), true);
}
You can use Directory.GetFiles along with SearchOption.AllDirectories to extract the files from the sub-folders as well:
Directory.GetFiles(path, *search pattern goes here*, SearchOption.AllDirectories)
I'm trying to match a file name to a partial string in a List. The list will have something like 192 in it and the matching file will be xxx192.dat. Using .Contains does not match the file name to the string in the List. Can anyone tell me how to get this done or how to use wildcard chars in the contains?
Code below.
// use this to get a specific list of files
private List<string> getFiles(string path, List<string> filenames)
{
List<string> temp = new List<string>();
string mapPath = Server.MapPath(path);
//DirectoryInfo Di = new DirectoryInfo(mapPath);
DirectoryInfo Di = new DirectoryInfo(#"C:\inetpub\wwwroot\Distribution\" + path); // for testing locally
FileInfo[] Fi = Di.GetFiles();
foreach (FileInfo f in Fi)
{
if (filenames.Contains(f.Name)) **// *** this never matches**
temp.Add(f.FullName);
}
return temp;
}
I'v changed the code trying to use the suggestions but it's still not working. I'll add in the data like I'm stepping through the code.
// use this to get a specific list of files
private List<string> getFiles(string path, List<string> filenames)
{
List<string> temp = new List<string>();
string mapPath = Server.MapPath(path);
//DirectoryInfo Di = new DirectoryInfo(mapPath);
DirectoryInfo Di = new DirectoryInfo(#"C:\inetpub\wwwroot\Distribution\" + path); // for testing locally
foreach (string s in filenames) // list has 228,91,151,184 in it
{
FileInfo[] Fi = Di.GetFiles(s); // s = 228: Fi = {System.IO.FileInfo[0]}
foreach (FileInfo f in Fi) //Fi = {System.IO.FileInfo[0]}
{
temp.Add(f.FullName);
}
}
return temp;
}
When I look at the directory where these files are I can see:
pbset228.dat
pbmrc228.dat
pbput228.dat
pbext228.dat
pbget228.dat
pbmsg228.dat
This is working now. It may not be the most efficient way to do this, but it gets the job done. Maybe someone can post a sample that does the same thing in a better way.
// use this to get a specific list of files
private List<string> getFiles(string path, List<string> filenames)
{
List<string> temp = new List<string>();
string mapPath = Server.MapPath(path);
//DirectoryInfo Di = new DirectoryInfo(mapPath);
DirectoryInfo Di = new DirectoryInfo(#"C:\inetpub\wwwroot\Distribution\" + path); // for testing locally
FileInfo[] Fi = Di.GetFiles();
foreach (FileInfo f in Fi)
{
foreach (string s in filenames)
{
if (f.Name.Contains(s))
temp.Add(f.FullName);
}
}
return temp;
}
You can use the Any() LINQ extension:
filenames.Any(s => s.EndsWith(f.Name));
This will return True if any element in the enumeration returns true for the given function.
For anything more complex, you could use a regular expression to match:
filenames.Any(s => Regex.IsMatch(s, "pattern"));
Use the static Directory.GetFiles method that lets you include a wildcards and will be more efficient that retrieving all the files and then having to iterate through them.
Or you can even use DirectoryInfo.GetFiles and pass your search string to that.
Change this
foreach (FileInfo f in Fi)
{
if (filenames.Contains(f.Name)) **// *** this never matches**
temp.Add(f.FullName);
}
return temp;
Into something like this
temp = filenames.Find(file => file.Contains(someNameYoureLookingFor));
Is there any way to exclude certain directories from SearchOption using LINQ command like this
string path = "C:\SomeFolder";
var s1 = Directory.GetFiles(path , "*.*", SearchOption.AllDirectories);
var s2 = Directory.GetDirectories(path , "*.*", SearchOption.AllDirectories);
The path consists of Sub1 and Sub2 Folders with certain files in it. I need to exclude them from directory search.
Thanks
This Worked:
string[] exceptions = new string[] { "c:\\SomeFolder\\sub1",
"c:\\SomeFolder\\sub2" };
var s1 = Directory.GetFiles("c:\\x86", "*.*",
SearchOption.AllDirectories).Where(d => exceptions.All(e =>
!d.StartsWith(e)));
This helped with Exceptions
No there isn't as far as I know. But you could use very simple LINQ to do that in a single line.
var s1 = Directory.GetFiles(path , "*.*", SearchOption.AllDirectories).Where(d => !d.StartsWith("<EXCLUDE_DIR_PATH>")).ToArray();
You can easily combine multiple exclude DIRs too.
You can't do exactly what you want with simple LINQ methods. You will need to write a recursive routine instead of using SearchOption.AllDirectories. The reason is that you want to filter directories not files.
You could use the following static method to achieve what you want:
public static IEnumerable<string> GetFiles(
string rootDirectory,
Func<string, bool> directoryFilter,
string filePattern)
{
foreach (string matchedFile in Directory.GetFiles(rootDirectory, filePattern, SearchOption.TopDirectoryOnly))
{
yield return matchedFile;
}
var matchedDirectories = Directory.GetDirectories(rootDirectory, "*.*", SearchOption.TopDirectoryOnly)
.Where(directoryFilter);
foreach (var dir in matchedDirectories)
{
foreach (var file in GetFiles(dir, directoryFilter, filePattern))
{
yield return file;
}
}
}
You would use it like this:
var files = GetFiles("C:\\SearchDirectory", d => !d.Contains("AvoidMe", StringComparison.OrdinalIgnoreCase), "*.*");
Why the added complexity? This method completely avoids looking inside directories you're not interested in. The SearchOption.AllDirectories will, as the name suggests, search within all directories.
If you're not familiar with iterator methods (the yield return syntax), this can be written differently: just ask!
Alternative
This has almost the same effect. However, it still finds files within subdirectories of the directories you want to ignore. Maybe that's OK for you; the code is easier to follow.
public static IEnumerable<string> GetFilesLinq(
string root,
Func<string, bool> directoryFilter,
string filePattern)
{
var directories = Directory.GetDirectories(root, "*.*", SearchOption.AllDirectories)
.Where(directoryFilter);
List<string> results = new List<string>();
foreach (var d in directories)
{
results.AddRange(Directory.GetFiles(d, filePattern, SearchOption.TopDirectoryOnly));
}
return results;
}
try this
var s2 = Directory.GetDirectories(dirPath, "*", SearchOption.AllDirectories)
.Where(directory => !directory.Contains("DirectoryName"));
///used To Load Files And Folder information Present In Dir In dir
private void button1_Click(object sender, EventArgs e)
{
FileInfo[] fileInfoArr;
StringBuilder sbr=new StringBuilder();
StringBuilder sbrfname = new StringBuilder();
string strpathName = #"C:\Users\prasad\Desktop\Dll";
DirectoryInfo dir = new DirectoryInfo(strpathName);
fileInfoArr = dir.GetFiles("*.dll");
//Load Files From RootFolder
foreach (FileInfo f in fileInfoArr)
{
sbrfname.AppendLine(f.FullName);
}
DirectoryInfo[] dirInfos = dir.GetDirectories("*.*");
//Load Files from folder folder
foreach (DirectoryInfo d in dirInfos)
{
fileInfoArr = d.GetFiles("*.dll");
foreach (FileInfo f in fileInfoArr)
{
sbrfname.AppendLine(f.FullName);
}
sbr.AppendLine(d.ToString());
}
richTextBox1.Text = sbr.ToString();
richTextBox2.Text = sbrfname.ToString();
}
I create a FileInfo array like this
try
{
DirectoryInfo Dir = new DirectoryInfo(DirPath);
FileInfo[] FileList = Dir.GetFiles("*.*", SearchOption.AllDirectories);
foreach (FileInfo FI in FileList)
{
Console.WriteLine(FI.FullName);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
And this array holds all the file names in folder = DirPath
I thought of looping through the FileInfo array and copy it to a String array. Is this ok or is there a much cleaner method ?
Using LINQ:
FileList.Select(f => f.FullName).ToArray();
Alternatively, using Directory you can get filenames directly.
string[] fileList = Directory.GetFiles(DirPath, "*.*",
SearchOption.AllDirectories);
If you want to go the other way (convert string array into FileInfo's) you can use the following:
string[] files;
var fileInfos = files.Select(f => new FileInfo(f));
List<FileInfo> infos = fileInfos.ToList<FileInfo>();
the linq is a great soluction, but for the persons who don't want to use linq, i made this function:
static string BlastWriteFile(FileInfo file)
{
string blasfile = " ";
using (StreamReader sr = file.OpenText())
{
string s = " ";
while ((s = sr.ReadLine()) != null)
{
blasfile = blasfile + s + "\n";
Console.WriteLine();
}
}
return blasfile;
}
Try this one
DirectoryInfo directory = new DirectoryInfo("your path");
List<string> Files = (directory.GetFiles().Where(file => file.LastWriteTime >= date_value)).Select(f => f.Name).ToList();
If you don't want a filter with date, you can simply convert with the below code
List<string> logFiles = directory.GetFiles().Select(f => f.Name).ToList();
If you need the full path of the file, you can use FullName instead of Name.
I am trying to get all images from folder but ,this folder also include sub folders. like /photos/person1/ and /photos/person2/ .I can get photos in folder like
path= System.IO.Directory.GetCurrentDirectory() + "/photo/" + groupNO + "/";
public List<String> GetImagesPath(String folderName)
{
DirectoryInfo Folder;
FileInfo[] Images;
Folder = new DirectoryInfo(folderName);
Images = Folder.GetFiles();
List<String> imagesList = new List<String>();
for (int i = 0; i < Images.Length; i++)
{
imagesList.Add(String.Format(#"{0}/{1}", folderName, Images[i].Name));
// Console.WriteLine(String.Format(#"{0}/{1}", folderName, Images[i].Name));
}
return imagesList;
}
But how can I get all photos in all sub folders? I mean I want to get all photos in /photo/ directory at once.
Have a look at the DirectoryInfo.GetFiles overload that takes a SearchOption argument and pass SearchOption.AllDirectories to get the files including all sub-directories.
Another option is to use Directory.GetFiles which has an overload that takes a SearchOption argument as well:
return Directory.GetFiles(folderName, "*.*", SearchOption.AllDirectories)
.ToList();
I'm using GetFiles wrapped in method like below:
public static String[] GetFilesFrom(String searchFolder, String[] filters, bool isRecursive)
{
List<String> filesFound = new List<String>();
var searchOption = isRecursive ? SearchOption.AllDirectories : SearchOption.TopDirectoryOnly;
foreach (var filter in filters)
{
filesFound.AddRange(Directory.GetFiles(searchFolder, String.Format("*.{0}", filter), searchOption));
}
return filesFound.ToArray();
}
It's easy to use:
String searchFolder = #"C:\MyFolderWithImages";
var filters = new String[] { "jpg", "jpeg", "png", "gif", "tiff", "bmp", "svg" };
var files = GetFilesFrom(searchFolder, filters, false);
There's a good one-liner solution for this on a similar thread:
get all files recursively then filter file extensions with LINQ
Or if LINQ cannot be used, then use a RegEx to filter file extensions:
var files = Directory.GetFiles("C:\\path", "*.*", SearchOption.AllDirectories);
List<string> imageFiles = new List<string>();
foreach (string filename in files)
{
if (Regex.IsMatch(filename, #"\.jpg$|\.png$|\.gif$"))
imageFiles.Add(filename);
}
I found the solution this Might work
foreach (string img in Directory.GetFiles(Environment.GetFolderPath(Environment.SpecialFolder.Desktop),"*.bmp" + "*.jpg" + "SO ON"))
You need the recursive form of GetFiles:
DirectoryInfo.GetFiles(pattern, searchOption);
(specify AllDirectories as the SearchOption)
Here's a link for more information:
MSDN: DirectoryInfo.GetFiles
This allows you to use use the same syntax and functionality as Directory.GetFiles(path, pattern, options); except with an array of patterns instead of just one.
So you can also use it to do tasks like find all files that contain the word "taxes" that you may have used to keep records over the past year (xlsx, xls, odf, csv, tsv, doc, docx, pdf, txt...).
public static class CustomDirectoryTools {
public static string[] GetFiles(string path, string[] patterns = null, SearchOption options = SearchOption.TopDirectoryOnly) {
if(patterns == null || patterns.Length == 0)
return Directory.GetFiles(path, "*", options);
if(patterns.Length == 1)
return Directory.GetFiles(path, patterns[0], options);
return patterns.SelectMany(pattern => Directory.GetFiles(path, pattern, options)).Distinct().ToArray();
}
}
In order to get all image files on your c drive you would implement it like this.
string path = #"C:\";
string[] patterns = new[] {"*.jpg", "*.jpeg", "*.jpe", "*.jif", "*.jfif", "*.jfi", "*.webp", "*.gif", "*.png", "*.apng", "*.bmp", "*.dib", "*.tiff", "*.tif", "*.svg", "*.svgz", "*.ico", "*.xbm"};
string[] images = CustomDirectoryTools.GetFiles(path, patterns, SearchOption.AllDirectories);
You can use GetFiles
GetFiles("*.jpg", SearchOption.AllDirectories)
GetFiles("*.jpg", SearchOption.AllDirectories) has a problem at windows7. If you set the directory to c:\users\user\documents\, then it has an exception: because of windows xp, win7 has links like Music and Pictures in the Documents folder, but theese folders don't really exists, so it creates an exception. Better to use a recursive way with try..catch.
This will get list of all images from folder and sub folders and it also take care for long file name exception in windows.
// To handle long folder names Pri external library is used.
// Source https://github.com/peteraritchie/LongPath
using Directory = Pri.LongPath.Directory;
using DirectoryInfo = Pri.LongPath.DirectoryInfo;
using File = Pri.LongPath.File;
using FileInfo = Pri.LongPath.FileInfo;
using Path = Pri.LongPath.Path;
// Directory and sub directory search function
public void DirectoryTree(DirectoryInfo dr, string searchname)
{
FileInfo[] files = null;
var allFiles = new List<FileInfo>();
try
{
files = dr.GetFiles(searchname);
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
if (files != null)
{
try
{
foreach (FileInfo fi in files)
{
allFiles.Add(fi);
string fileName = fi.DirectoryName + "\\" + fi.Name;
string orgFile = fileName;
}
var subDirs = dr.GetDirectories();
foreach (DirectoryInfo di in subDirs)
{
DirectoryTree(di, searchname);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
}
public List<String> GetImagesPath(String folderName)
{
var dr = new DirectoryInfo(folderName);
string ImagesExtensions = "jpg,jpeg,jpe,jfif,png,gif,bmp,dib,tif,tiff";
string[] imageValues = ImagesExtensions.Split(',');
List<String> imagesList = new List<String>();
foreach (var type in imageValues)
{
if (!string.IsNullOrEmpty(type.Trim()))
{
DirectoryTree(dr, "*." + type.Trim());
// output to list
imagesList.Add = DirectoryTree(dr, "*." + type.Trim());
}
}
return imagesList;
}
var files = new DirectoryInfo(path).GetFiles("File")
.OrderByDescending(f => f.LastWriteTime).First();
This could gives you the perfect result of searching file with its latest mod