Search file in Directory using partial name in C# - c#

I need to search file in directory using partial name.
Ex:
Directory : c:\Path
Filename : Error_005296-895632-12563.xml
Partial file name: 005296-895632-12563
I have tried below.
Directory.GetFiles("c:\Path", "*005296-895632-12563*.xml", SearchOption.AllDirectories).
But it didn't work
Sample file names are :
Error_005296-895632-12563.xml
005296-895632-12563_Response.xml
Duplicate_005296-895632-12563_Response.xml

You can create a extension method and pass the array of partial names which you want to find.
Call the extension method like this
DirectoryInfo dir = new DirectoryInfo(#"c:\demo");
FileInfo[] files = dir.GetFilesBypartialName("Anc_def_", "ABC_123", "12_qweqweqw_123").ToArray();
below is the extension method
public static class DirectoryFindFile
{
public static IEnumerable<FileInfo> GetFilesBypartialName(this DirectoryInfo dirInfo, params string[] partialFilenames)
{
if (partialFilenames == null)
throw new ArgumentNullException("partialFilenames");
var lstpartialFilenames = new HashSet<string>(partialFilenames, StringComparer.OrdinalIgnoreCase);
return dirInfo.EnumerateFiles()
.Where(f => lstpartialFilenames.Contains(f.Name));
}
public static IEnumerable<FileInfo> GetFilesBypartialFilenamesAllDir(this DirectoryInfo dirInfo, params string[] partialFilenames)
{
if (partialFilenames == null)
throw new ArgumentNullException("partialFilenames");
var lstpartialFilenames = new HashSet<string>(partialFilenames, StringComparer.OrdinalIgnoreCase);
return dirInfo.EnumerateFiles("*.*", SearchOption.AllDirectories)
.Where(f => lstpartialFilenames.Contains(f.Name));
}
}

Heres a extension function I've used to search directories
public static IEnumerable<string> GetFiles(string path, string searchPatternExpression = "", SearchOption searchOption = SearchOption.AllDirectories)
{
Regex reSearchPattern = new Regex(searchPatternExpression);
return Directory.EnumerateFiles(path, "*", searchOption).Where(file => reSearchPattern.IsMatch(System.IO.Path.GetExtension(file)));
}

Related

Looking for folders in multiple extension and multiple string format

Hi I am trying to get all the files with a set of extension and a set of string format
string extensions=".exe,.txt,.xls";
string fileFormat"fileA, fileB, fileC";
let says if i have the following files in the folder
fileA20200805.txt
fileBxxxx.exe
FileCCCCCCC.txt
FileD123.xls
the result should only return the first 3 files which is
fileA20200805.txt
fileBxxxx.exe
FileCCCCCCC.txt
because FileD123.xls is not in the fileFormat.
I have tried the following code:
Directoryinfo dInfo = new DirectoryInfo(path);
FileInfo[] files = dInfoGetFiles()
.Where(f => extensions.Contains(f.Extension.ToLower()) && fileFormat.Any(f.Name.Contains))
.ToArray();
However, I am still getting all 4 files, the FileD123.xls is still returning
Maybe
var extensions = new [] {".exe",".txt",".xls"};
var fileFormat = new [] {"fileA", "fileB", "fileC"};
...
.Where(f =>
extensions.Contains(f.Extension.ToLower()) &&
fileFormat.Any(x => f.Name.StartsWith(x, StringComparison.OrdinalIgnoreCase)))
You could also use regex i guess
var regex = new Regex(#$"({string.Join("|", fileFormat)}[^.]*({string.Join(" | ", extensions)})", RegexOptions.Compiled|RegexOptions.IgnoreCase);
...
.Where(f => regex.IsMatch(f.Name))
I think this should work.
string[] extensions = new string[] { ".exe",".txt",".xls" };
string[] fileFormat = new string[] { "fileA", "fileB", "fileC" };
DirectoryInfo dInfo = new DirectoryInfo(path);
FileInfo[] files = dInfo.GetFiles();
var output = files.Where(f => extensions.Contains(f.Extension.ToLower()) &&
fileFormat.Any(f.Name.Contains)).ToArray();
it return 2 because FileCCCCCCC dont equals fileC.

Return a list of Directory (Folder) names that match a partial string

I need someone to point me in the right direction.
Goal:
Return a list of Folder Names in a path that contain a string in their name. For example: The Path has a Directory named Pictures_New and Videos_New. The string I am searching with is "Pictures_" and "Videos_".
It all works with one string parameter being passed as a search string. My problem is getting it to work with multiple filters. I know it is easily done with file names and extensions.
This is being passed to GetFolders():
string[] filterStrings = { "Pictures_", "Videos_" }
Rest of my code:
public IEnumerable<string> GetFolders(string path, string[] filterStrings, SearchOption searchOption = SearchOption.AllDirectories)
{
IEnumerable<string> folders = Directory.EnumerateDirectories(path, "Pictures_*.*", searchOption);
var resultFolders = new List<string>();
if(filterStrings.Length > 0)
{
foreach (var foldername in folders)
{
string folderName = Path.GetFileName(Path.GetDirectoryName(foldername));
if (string.IsNullOrEmpty(folderName) || Array.IndexOf(filterStrings, "*" + folderName) < 0)
{
// This leaves us only with the Directory names. No paths.
var b = (foldername.Substring(foldername.LastIndexOf(#"\") + 1));
resultFolders.Add(b);
}
}
}
return resultFolders;
}
You can use Linq SelectMany to parse your list of filters and return a list of the results with Directory.GetDirectories();
It will of course return all the Sub Directories that match the filter. Use just "*".
public IEnumerable<string> GetFolders(string path, string[] filterStrings, SearchOption searchOption = SearchOption.AllDirectories)
{
List<string> resultFolders = filterStrings
.SelectMany(flt => Directory.GetDirectories(path, flt, searchOption))
.ToList();
return resultFolders;
}
try:
var patterns = new[] { "Pictures_*", "Videos_*" };
var dirsFound = new List<string>();
foreach (var dir in patterns.Select(pattern => Directory.GetDirectories(#"my path", pattern).ToArray()))
{
dirsFound.AddRange(dir);
}
Looks like you're not looping through each of your filter strings:
var folders = new List<string>();
foreach (var filterString in filterStrings)
{
folders.AddRange(Directory.EnumerateDirectories(path, filterString, searchOption););
}

Trying to get file names without path or extension and output to a list.

Was given this by a coworker but I need just file names:
private List<string> getWavFileList()
{
string path = #"c\test automation\wave files";
string[] files = Directory.GetFiles(path, "*.wav");
List<string> list = new List<string>(files);
return list;
}
The output list contains the path and extension and I need the file name only. I was working on my own method but can't get it to compile:
private List<string> getWavFileList()
{
StringBuilder builder = new StringBuilder();
string path = #"c\test automation\wave files";
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] smFiles = di.GetFiles("*.wav");
foreach (FileInfo fi in smFiles)
{
builder.Append(Path.GetFileNameWithoutExtension(fi.Name));
builder.Append(", ");
}
string files = builder.ToString();
List list = new List<string>(files);
return list;
I'd suggest modifying to something like the following;
private List<string> getWavFileList()
{
string path = #"c:\test automation\wave files";
DirectoryInfo di = new DirectoryInfo(path);
FileInfo[] smFiles = di.GetFiles("*.wav");
List<string> list = new List<string>(smFiles.Select(f => Path.GetFileNameWithoutExtension(f.Name)));
return list;
}
In the first solution replace this line
List<string> list = new List<string>(files);
with this:
return files.Select(Path.GetFileNameWithoutExtension).ToList();
This requires using of System.Linq.
I don't know why you are concatenating strings with comma, i thought you wanted a list:
private List<string> getWavFileList()
{
return Directory.EnumerateFiles(#"c\test automation\wave files", "*.wav")
.Select(System.IO.Path.GetFileNameWithoutExtension)
.ToList();
}

Directory.EnumerateFiles method: How to enumerate files in specified subdirectories?

Assume the following directory structure. "C:\Genre" and the "Genre" directory having several subdirectories: "Rock", "Pop", "Metal", "Jazz".
How would I tweak the following statement to search in "Rock" and "Metal" subdirectories only?
var myFiles = Directory.
EnumerateFiles("C:\Genre", "*", SearchOption.AllDirectories).
Where(s => s.EndsWith(".jpg") || s.EndsWith(".gif"));
I'd say the clean way would be search each directory you want, and then add them up in the myFiles
var rockFiles = Directory.EnumerateFiles("c:\Genre\Rock", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".jpg") || s.EndsWith(".gif"));
var metalFiles = Directory.EnumerateFiles("c:\Genre\Metal", "*", SearchOption.AllDirectories).Where(s => s.EndsWith(".jpg") || s.EndsWith(".gif"));
var myFiles = RockFiles.Concat(MetalFiles);
Now, if you want a generic way to do so, that would be a different story, and a bit more complex one :)
Please consider some implementation like this one:
public static class Program
{
public static void Main()
{
var directoryPaths = new List<string>
{
#"C:\root\path_1",
#"C:\root\path_2",
#"C:\root\path_3"
// …
};
var searchPatterns = new List<string>
{
"*.jpg",
"*.gif"
};
var filePaths = directoryPaths
.SelectMany(directoryPath =>
EnumerateFiles(directoryPath, searchPatterns, SearchOption.AllDirectories))
.ToList()
.AsReadOnly();
// …
}
private static IEnumerable<string> EnumerateFiles(
string path,
IEnumerable<string> searchPatterns,
SearchOption searchOption)
{
var filePaths = searchPatterns.SelectMany(
searchPattern => Directory.EnumerateFiles(path, searchPattern, searchOption));
return filePaths;
}
}
Use Concat in Linq to combine the files in two directories.
var rockFiles = Directory.
EnumerateFiles("C:\Genre\Rock", "*", SearchOption.AllDirectories);
var metalFiles = Directory.
EnumerateFiles("C:\Genre\Metal", "*", SearchOption.AllDirectories);
var myFiles = rockFile
.Concat(metalFiles)
.Where(s => s.EndsWith(".jpg") || s.EndsWith(".gif"));
You could use two arrays for the extensions and the Path-class:
var myFiles = Directory.EnumerateFiles(#"C:\Temp\Genre", "*", SearchOption.AllDirectories)
.Where(fn => genres.Contains(Path.GetFileName(Path.GetDirectoryName(fn)), StringComparer.InvariantCultureIgnoreCase)
&& extensions.Contains(Path.GetExtension(fn), StringComparer.InvariantCultureIgnoreCase));
Path.GetFileName(Path.GetDirectoryName(fn)) returns the folder-name of a file-path.

recursively scan all the directories under the root directory and find only the newest file from each folder

that's what i try but it return only the newest file from only the top directories under the root
if(Directory.Exists("YourPath"))
foreach (string _tempFiles in Directory.GetDirectories("YourPath")
.Select(directory => Directory.GetFiles(directory, "*.*", SearchOption.AllDirectories)
.OrderByDescending(File.GetLastWriteTime)
.FirstOrDefault()))
This returns all newest files of each directory(including root):
var rootDirFile = Directory
.EnumerateFiles(yourPath, "*.*", SearchOption.TopDirectoryOnly)
.OrderByDescending(f => File.GetLastWriteTime(f))
.Take(1);
var allNewestFilesOfEachFolder = Directory
.EnumerateDirectories(yourParth, "*.*", SearchOption.AllDirectories)
.Select(d => Directory.EnumerateFiles(d, "*.*")
.OrderByDescending(f => File.GetLastWriteTime(f))
.FirstOrDefault());
// put both together, the root-file first
allNewestFilesOfEachFolder = rootDirFile.Concat(allNewestFilesOfEachFolder);
If there's no file in a directory the file is null, so the number of files is equal to the number of folders.
Note that Linq is not the right tool for System.IO since error-handling is difficult.
I wrote a basic recursive function to handle this:
// Dictionary:
// Key = The directory name.
// Value = The most recently modified file for that directory.
public static Dictionary<string, string> GetNewestFiles(string directory)
{
return GetNewestFiles(directory, null);
}
static Dictionary<string, string> GetNewestFiles(string directory,
Dictionary<string, string> dictionary)
{
if(dictionary == null)
dictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
try
{
var files = from file in Directory.GetFiles(directory)
select new FileInfo(file);
var latestFile = files.OrderByDescending(file => { return file.LastWriteTimeUtc; }).FirstOrDefault();
if (latestFile != null)
dictionary[latestFile.DirectoryName] = latestFile.FullName;
}
catch { }
foreach (var subDirectory in Directory.GetDirectories(directory))
{
try
{
GetNewestFiles(subDirectory, dictionary);
}
catch { }
}
return dictionary;
}
So then you can just call it like so:
var fileDictionary = GetNewestFiles(#"C:\MyFolder");

Categories

Resources