I am trying to get .mp3 files from multiple folders.
I can already do it for one folder through this query :
this.MusicList.ItemsSource =
from string fileName in Directory.GetFiles(#"C:\Users\Public\Music\Sample Music")
where System.IO.Path.GetExtension(fileName) == ".mp3"
select new FileInfo(fileName);
Is there any other way to do it for a list of directories ?
Here is what I have tried so far (returns no results):
var paths = new Dictionary<string, string> {
{"default_music", #"C:\Users\Public\Music\Sample Music"},
{"alternative_folder", #"C:\tmp"}
};
this.MusicList.ItemsSource =
from string fileName in (from string directoryName in paths.Values select Directory.GetFiles(directoryName))
where System.IO.Path.GetExtension(fileName) == ".mp3"
select new FileInfo(fileName);
from string directoryName in paths.Values select Directory.GetFiles(directoryName); returns a {System.Linq.Enumerable.WhereSelectEnumerableIterator<string,string[]>} with my paths in its source field and its Result View contains of my .mp3 files.
Thank you
Try the following
this.MusicList.ItemsSource =
from path in paths
from fileName in Directory.GetFiles(path)
where System.IO.Path.GetExtension(fileName) == ".mp3"
select new FileInfo(fileName);
Strict method call version
this.MusicList.ItemSource = paths
.SelectMany(path => Directory.GetFiles(path))
.Where(fileName => System.IO.Path.GetExtension(fileName) == ".mp3")
.Select(fileName => new FileInfo(fileName));
You can use DirectoryInfo.EnumerateFiles method which accepts search pattern. Thus you don't need to get all files and filter them via calls to Path.GetExtension
var paths = new Dictionary<string, string> {
{"default_music", #"C:\Users\Public\Music\Sample Music"},
{"alternative_folder", #"C:\tmp"}
};
MusicList.ItemsSource = paths.Values.Select(p => new DirectoryInfo(p))
.SelectMany(d => d.EnumerateFiles("*.mp3"));
Also DirectoryInfo.EnumerateFiles returns FileInfo instances, which is also what you want.
Try this
Directory.EnumerateFiles(#"C:\Users\Public\Music\Sample Music", "*.mp3", SearchOption.AllDirectories)
to return an enumerable list of .mp3's, which you can further filter or enumerate etc. This is more efficient than GetFiles() for large numbers of files and/or directories.
http://msdn.microsoft.com/en-us/library/dd383571.aspx
Alternate to the esteemable JaredPar that tracks if it's a File/Directory:
var basePath = #"c:\temp";
var query =
from entry in Directory.EnumerateFileSystemEntries(basePath, "*.*", SearchOption.AllDirectories)
let isDirectory = Directory.Exists(entry)
let isFile = File.Exists(entry)
select new { isDirectory, isFile, entry};
query.Dump();
EDIT: Doh - misread question, missed the "from a set of directories" part; my shame is immeasurable. :)
Related
I was wondering if there was a way to only retrieve the directories that have certain extensions.
For example
List<string> directories = Directory.GetDirectories(sourceTextBox.Text, "*", SearchOption.AllDirectories).ToList();
would give me all of the directories and subdirectories inside the path I gave it. However I only want it to retrieve the directories that have a .jpg or .png file inside of them.
List<string> directories = Directory.GetDirectories(sourceTextBox.Text, "*.png", SearchOption.AllDirectories).ToList();
directories.addRange(Directory.GetDirectories(sourceTextBox.Text, "*.jpg", SearchOption.AllDirectories).ToList());
Any way I could do this?
No guarantees in terms of performance, but for each directory you could check its files to see if it contains any with the matching extension:
List<string> imageDirectories = Directory.GetDirectories(sourceTextBox.Text, "*", SearchOption.AllDirectories)
.Where(d => Directory.EnumerateFiles(d)
.Select(Path.GetExtension)
.Where(ext => ext == ".png" || ext == ".jpg")
.Any())
.ToList();
There is no built in way of doing it, You can try something like this
var directories = Directory
.GetDirectories(path, "*", SearchOption.AllDirectories)
.Where(x=> Directory.EnumerateFiles(x, "*.jpg").Any() || Directory.EnumerateFiles(x, "*.png").Any())
.ToList();
You can use Directory.EnumerateFiles method to get the file matching criteria and then you can get their Path minus file name using Path.GetDirectoryName and add it to the HashSet. HashSet would only keep the unique entries.
HashSet<string> directories = new HashSet<string>();
foreach(var file in Directory.EnumerateFiles(sourceTextBox.Text,
"*.png",
SearchOption.AllDirectories))
{
directories.Add(Path.GetDirectoryName(file));
}
For checking multiple file extensions you have to enumerate all files and then check for extension for each file like:
HashSet<string> directories = new HashSet<string>();
string[] allowableExtension = new [] {"jpg", "png"};
foreach(var file in Directory.EnumerateFiles(sourceTextBox.Text,
"*",
SearchOption.AllDirectories))
{
string extension = Path.GetExtension(file);
if (allowableExtension.Contains(extension))
{
directories.Add(Path.GetDirectoryName(file));
}
}
I know how to get the last file, this the code:
string pattern = "Log*.xml";
string directory = set. Path;
var dirInfo = new DirectoryInfo(directory);
var file = (from f in dirInfo.GetFiles(pattern) orderby f.LastWriteTime descending select f).First();
My question is: How can I get the last file that not contain specific string? or in another words, how can I get the last file that not contain "This is temporally file" string?
Thank you!
from top of my head:
dirInfo.EnumerateFiles(pattern)
.OrderByDescending(f => f.LastWriteTime)
.Where(f => DoesntContain(f, myText))
.FirstOrDefault()
Now you are free to make DoesntContain as complex or simple as you want. Either use File.ReadAllText or something like:
bool DoesntContain(FileInfo fileInfo, string text) {
using (StreamReader r = fileInfo.OpenText()) {
var contents = r.ReadToEnd();
return !contents.Contains(text);
}
}
You can write the method as extension to get more natural syntax like fi.DoesntContain(...)
Additionally, I suggest using EnumerateFiles instead of GetFiles if the directory can contain many files: there is no need to retrieve them all, if the first one will match.
You can do something like this:
string pattern = "Log*.xml";
var dirInfo = new DirectoryInfo(directory);
var filesThatContains = dirInfo.GetFiles(pattern).
Where(f=>File.ReadAllLines(Path.Combine(directory, f.Name),
Encofing.UTF8).IndexOf(SEARCH_STRING)>=0);
I would do something simpler for a start:
public static string[] FileNamesExcluding(string path, string pattern, string textToExclude)
{
// Put all txt files in root directory into array.
string[] allFilesMatchingPattern = Directory.GetFiles(path, pattern); // <-- Case-insensitive
return allFilesMatchingPattern.SkipWhile(a => a.Contains(textToExclude)).ToArray();
}
To call this method you can do:
FileNamesExcluding(#"C:\", "*.sys", "config").Last();
I have the following piece of code:
string root = Path.GetDirectoryName(Application.ExecutablePath);
List<string> FullFileList = Directory.GetFiles(root, "*.*",
SearchOption.AllDirectories).Where(name =>
{
return !(name.EndsWith("dmp") || name.EndsWith("jpg"));
}).ToList();
Now this works very well, however the file names with it are quire long.
is there a way i can take out the path till root? but still show all the subfolders?
Root = C:\Users\\Desktop\Test\
But the code would return the whole path from C:
while I'd prefer if I could take out the root bit straight away. but still keep the file structure after it.
eg
C:\Users\\Desktop\Test\hi\hello\files.txt
would return
\hi\hello\files.txt
I know i can just iterate over the file list generated and remove it all one by one, I'm wondering if I can just filter it out stright.
Using the power of LINQ:
string root = Path.GetDirectoryName(Application.ExecutablePath);
List<string> FullFileList = Directory.GetFiles(root, "*.*", SearchOption.AllDirectories)
.Where(name =>
{
return !(name.EndsWith("dmp") || name.EndsWith("jpg"));
})
.Select(file => file.Replace(root, "")
.ToList();
I have an array of files, but the problem is the root path isn't attached to the file, so using the data below, how would I go about appending the linq item to the static string?
string rootPath = "C:\\Users\\MyUserName";
List<string> files = new List<string>();
files.Add("\\My Documents\\File1.txt");
files.Add("\\My Documents\\File2.txt");
I essentially want a list that is Path.Combine(rootPath, x); I tried this but no luck:
var fileList = (from x in files
select Path.Combine(rootPath, x)).ToList();
But it doesn't append the rootPath, fileList is the same as the files list.
Any ideas?
Apparently Path.Combine will ignore the first parameter if the second parameter has a leading "\" (this blog entry has some more info).
This should work, it uses Path.Combine and the ? operator to account for leading slashes in the second parameter:
var fileList = (from f in files
select Path.Combine(rootPath,
f.StartsWith("\\") ? f.Substring(1) : f)).ToList();
the query works fine if you change
"\\My Documents\\File1.txt" to #"My Documents\\File1.txt" .
The reason is being described in the post mentioned by Donut.
Hence,
string rootPath = "C:\\Users\\MyUserName";
List<string> files = new List<string>();
files.Add(#"My Documents\\File1.txt");
files.Add(#"My Documents\\File2.txt");
var fileList = (from x in files select Path.Combine(rootPath, x)).ToList();
OR
var fileList = files.Select(i => Path.Combine(rootPath, i));
works fine.
If at all you donot want to change the existing source , then instead of Path.Combine use
string.Concat
e.g.
string rootPath = "C:\\Users\\MyUserName";
List<string> files = new List<string>();
files.Add("\\My Documents\\File1.txt");
files.Add("\\My Documents\\File2.txt");
var fileList = (from x in files select string.Concat(rootPath, x)).ToList();
OR
var fileList = files.Select(i => string.Concat(rootPath, i));
Hope this helps
How to exclude certain file type when getting files from a directory?
I tried
var files = Directory.GetFiles(jobDir);
But it seems that this function can only choose the file types you want to include, not exclude.
You should filter these files yourself, you can write something like this:
var files = Directory.GetFiles(jobDir).Where(name => !name.EndsWith(".xml"));
I know, this a old request, but about me it's always important.
if you want exlude a list of file extension: (based on https://stackoverflow.com/a/19961761/1970301)
var exts = new[] { ".mp3", ".jpg" };
public IEnumerable<string> FilterFiles(string path, params string[] exts) {
return
Directory
.GetFiles(path)
.Where(file => !exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)));
}
You could try something like this:
var allFiles = Directory.GetFiles(#"C:\Path\", "");
var filesToExclude = Directory.GetFiles(#"C:\Path\", "*.txt");
var wantedFiles = allFiles.Except(filesToExclude);
I guess you can use lambda expression
var files = Array.FindAll(Directory.GetFiles(jobDir), x => !x.EndWith(".myext"))
You can try this,
var directoryInfo = new DirectoryInfo("C:\YourPath");
var filesInfo = directoryInfo.GetFiles().Where(x => x.Extension != ".pdb");
Afaik there is no way to specify the exclude patterns.
You have to do it manually, like:
string[] files = Directory.GetFiles(myDir);
foreach(string fileName in files)
{
DoSomething(fileName);
}
This is my version on the answers I read above
List<FileInfo> fileInfoList = ((DirectoryInfo)new DirectoryInfo(myPath)).GetFiles(fileNameOnly + "*").Where(x => !x.Name.EndsWith(".pdf")).ToList<FileInfo>();
I came across this looking for a method to do this where the exclusion could use the search pattern rules and not just EndWith type logic.
e.g. Search pattern wildcard specifier matches:
* (asterisk) Zero or more characters in that position.
? (question mark) Zero or one character in that position.
This could be used for the above as follows.
string dir = #"C:\Temp";
var items = Directory.GetFiles(dir, "*.*").Except(Directory.GetFiles(dir, "*.xml"));
Or to exclude items that would otherwise be included.
string dir = #"C:\Temp";
var items = Directory.GetFiles(dir, "*.txt").Except(Directory.GetFiles(dir, "*HOLD*.txt"));
i used that
Directory.GetFiles(PATH, "*.dll"))
and the PATH is:
public static string _PATH = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);