GetDirectories - Find the directory that does not match the pattern - c#

I have 140 directories that I'm trying to process. According to my tests there are 139 directories that match my file pattern (*abc.txt).
I'm trying to find the 1 directory to verify that in fact it does not have a *abc.txt in it.
How can I do this?
The following code gives me the 140 directories number:
var directoryCount = from subdirectory in Directory.GetDirectories(paramStartFilePath, "*", SearchOption.AllDirectories)
where Directory.GetDirectories(subdirectory).Length == 0
select subdirectory;
I'm gathering the files based off the pattern like this:
dirInfoFiles= new DirectoryInfo(startFilePath);
IEnumerable<FileInfo> listFiles = dirInfoFiles.EnumerateFiles("*abc.txt, System.IO.SearchOption.AllDirectories);
How can I find the the one directory that doesn't contain my .txt file?

There is always the running the tank through the village approach: just enumerate *.* and then exclude the patterns that don't match.

If you want all directories that does not contain at least one txt-file which name ends with "abc":
IEnumerable<DirectoryInfo> matchingDirs = dirInfoFiles.EnumerateDirectories("*.*", System.IO.SearchOption.AllDirectories)
.Where(d => !d.EnumerateFiles().Any(f => f.Extension.ToUpper() == ".TXT"
&& f.Name.EndsWith("abc", StringComparison.OrdinalIgnoreCase)));
or the same in other words, possibly more readable:
IEnumerable<DirectoryInfo> matchingDirs = dirInfoFiles
.EnumerateDirectories("*.*", System.IO.SearchOption.AllDirectories)
.Where(d => !d.EnumerateFiles("*abc.txt").Any());

Here is my take. It returns the first item (or null) that contains a file ending with the text you are looking for and is case insensitive. You could remove the lambdas to make it more readable.
var directory = Directory.GetDirectories((paramStartFilePath, "*", SearchOption.AllDirectories)
.FirstOrDefault(x => new DirectoryInfo(x).EnumerateFiles().Any(f => !f.Name.EndsWith("abc.txt",true,CultureInfo.CurrentCulture)));

Related

DirectoryInfo.GetFiles with multiple filters

I am trying to get a list of FileInfo objects that satisfy multiple filters.
Every suggestion I have seen uses array of file names/paths instead of FileInfo:
var files = Directory.GetFiles(sLogPath, "*.*", SearchOption.TopDirectoryOnly)
.Where(s => s.StartsWith("abc", StringComparison.CurrentCultureIgnoreCase) || s.StartsWith("def", StringComparison.CurrentCultureIgnoreCase));
What I am trying to get is:
DirectoryInfo di = new DirectoryInfo(sLogPath);
var files = di.GetFiles(<same filter as above>);
But it looks like I can only do something like:
var files = di.GetFiles("*_" + dateStr + ".log");
Based on your comment to me on your question, it looks like you want to filter on file names, but get the FileInfos that correspond to these names.
You can do something like this
var di = new DirectoryInfo(sLogPath);
var files = di
.GetFiles("*.*", SearchOption.TopDirectoryOnly)
.Where(x => x.Name.StartsWith("abc", StringComparison.CurrentCultureIgnoreCase)
|| x.Name.StartsWith("def", StringComparison.CurrentCultureIgnoreCase))
.ToList();
We're using the Name property in the filter and working with the FileInfo[] array returned by DirectoryInfo.GetFiles().

Sort List<string> based on character count

Example:
List<string> folders = new List<string>();
folders.Add("folder1/folder2/folder3/");
folders.Add("folder1/");
folders.Add("folder1/folder2/");
I want to sort this list based on character i.e '/'
so my output will be
folder1/
folder1/folder2/
folder1/folder2/folder3
LINQ:
folders = folders.OrderBy(f => f.Length).ToList(); // consider null strings
or List.Sort
folders.Sort((s1, s2) => s1.Length.CompareTo(s2.Length));
a safe approach if the list could contain null's:
folders = folders.OrderBy(f => f?.Length ?? int.MinValue).ToList();
If you actually want to sort by the folder-depth not string length:
folders = folders.OrderBy(f => f.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar).Length).ToList();
It's likely you actually want to sort by name:
folders = folders.OrderBy(f => f).ToList();
Or simply:
folders.Sort();
This will work correctly for cases like this:
folder1/
folder1/subfolder1
folder1/subfolder1/subsubfolder
folder2
folder2/subfolder2
Sorting by length alone will consider "folder1" and "folder2" equal.

How to filter files with date from a folder in C#

I have c# code to get the pdf files from a folder.
string[] pdfFiles = Directory.GetFiles(EnvSettingsTools.FilePath.ToString(), "*.pdf")
.Select(path => Path.GetFileNameWithoutExtension(path))
.ToArray();
How can i use this code to get the files by filter by date. The file format will be
LondoPage 20160301.pdf
I need to filter the files with the date in the end of filename. i.e, if i pass date '20160301' the mentioned file should select.
Try
var date = "20160301";
string[] pdfFiles = Directory.GetFiles(EnvSettingsTools.FilePath.ToString(), "*.pdf")
.Select(path => Path.GetFileNameWithoutExtension(path))
.Where(f => f.EndsWith(date))
.ToArray();
This will get files whose name ends with date you pass for filter:
var date = "20160301";
string[] pdfFiles = Directory.GetFiles(EnvSettingsTools.FilePath.ToString(), "*.pdf")
.Select(Path.GetFileNameWithoutExtension)
.Where(f => f.EndsWith(date))
.ToArray();
I did not quite understand your desired outcome but I will do an educated guess that you need to be able to order or filter the folder content. That can be achieved in more than one way. I will propose a solution to your problem
if (!Directory.Exists(pathToFiles)) return;
DirectoryInfo di = new DirectoryInfo(pathToFiles);
FileSystemInfo[] files = di.GetFileSystemInfos();
var orderedFiles = files.OrderBy(f => f.CreationTime);
var filteredFileByDate = orderedFiles.Where(f => f.FullName.ToLowerInvariant().Split('/').Last().Contains("filterText"));
With the ordered files you will receive all files ordered by a particular property, in this case I have chosen the creation date.
With the filtered file you will receive a collection of one or more files that mach your criteria. The more precise is your criteria the less results you get.
Hope that it helps ;)

How to EnumerateFiles with all subdirectories with C# DirectoryInfo?

I found this code that gets an array of files out of a DirectoryInfo :
FileInfo[] fileInfoArray = di.EnumerateFiles().Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
But it only searches the direct children of the path of DirectoryInfo. i.e., it does not include grandchildren.
I guess I need to add SearchOption.AllDirectories parameter to somewhere, but where?
I tried :
di.EnumerateFiles(SearchOption.AllDirectories).Where(f => extensions.Contains(f.Extension.ToLower())).ToArray();
But it yields an error.
So how do I search with a pattern, including all subdirectories ?
Thanks for any help !
Look at the overloads of DirectoryInfo.EnumerateFiles - there's no overload taking just a SearchOption, but you can give a string and a SearchOption:
var files = di.EnumerateFiles("*", SearchOption.AllDirectories)
.Where(f => extensions.Contains(f.Extension.ToLower()))
.ToArray();

How to exclude folders when using Directory.GetDirectories

I want to return a list of all the subdirectories in the 'SomeFolder' directory excluding the 'Admin' and 'Templates' directories.
I have the following folder structure (simplified):
C:\inetpub\wwwroot\MyWebsite\SomeFolder\RandomString
C:\inetpub\wwwroot\MyWebsite\SomeFolder\RandomString
C:\inetpub\wwwroot\MyWebsite\SomeFolder\RandomString
C:\inetpub\wwwroot\MyWebsite\SomeFolder\Admin
C:\inetpub\wwwroot\MyWebsite\SomeFolder\Templates
'SomeFolder' can contain a varying number a 'RandomString' folders (anywhere from ~10 to ~100).
Here is what I have tried:
var dirs = Directory.GetDirectories(Server.MapPath(".."))
.Where(s => !s.EndsWith("Admin") || !s.EndsWith("Templates"));
foreach (string dir in dirs)
{
lit.Text += Environment.NewLine + dir;
}
This returns the full list of folders (shown above) without 'Admin' and 'Templates' filtered out.
Interestingly, if I change the LINQ .Where clause to include, instead of exclude, 'Admin' and 'Templates' it works, meaning it returns just the paths for 'Admin' and 'Templates'.
.Where(s => s.EndsWith("Admin") || s.EndsWith("Templates"));
If LINQ is not the solution, is there any way to use the GetDirectories SearchPattern to filter out directories?
You can do something like:
//list your excluded dirs
private List<string> _excludedDirectories= new List<string>() { "Admin", "Templates" };
//method to check
static bool isExcluded(List<string> exludedDirList, string target)
{
return exludedDirList.Any(d => new DirectoryInfo(target).Name.Equals(d));
}
//then use this
var filteredDirs = Directory.GetDirectories(path).Where(d => !isExcluded(_excludedDirectories, d));
the opposite of (A || B) is (!A && !B), so in your code it should be &&, not ||...

Categories

Resources