I have a folder with files named
myfileone
myfiletwo
myfilethree
How can I check if file "myfilethree" is present.
I mean is there another method other than IsFileExist() method, i.e like filename contains substring "three"?
Substring:
bool contains = Directory.EnumerateFiles(path).Any(f => f.Contains("three"));
Case-insensitive substring:
bool contains = Directory.EnumerateFiles(path).Any(f => f.IndexOf("three", StringComparison.OrdinalIgnoreCase) > 0);
Case-insensitive comparison:
bool contains = Directory.EnumerateFiles(path).Any(f => String.Equals(f, "myfilethree", StringComparison.OrdinalIgnoreCase));
Get file names matching a wildcard criteria:
IEnumerable<string> files = Directory.EnumerateFiles(path, "three*.*"); // lazy file system lookup
string[] files = Directory.GetFiles(path, "three*.*"); // not lazy
If I understand your question correctly, you could do something like
Directory.GetFiles(directoryPath, "*three*")
or
Directory.GetFiles(directoryPath).Where(f => f.Contains("three"))
Both of these will give you all the names of all files with three in it.
I am not that familiar with IO but maybe this would work ? Requires using System.Linq
System.IO.Directory.GetFiles("PATH").Where(s => s.Contains("three"));
EDIT: Note that this returns array of strings.
Related
I'm trying to fetch a particular filename from a directory. The code I've tried is as below
DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
FileInfo recentlyModLogFile = (from files in dirInfo.GetFiles("^Monarch_[0-9]{2}$") orderby files.LastWriteTime descending select files).First();
//Output : Error
List of file names (Input)
Monarch_05bridge //Date modified 16-12-2021 20:41
Monarch_04bridge //Date modified 16-12-2021 06:49
Monarch_04 //Date modified 16-12-2021 05:39
Monarch_02 //Date modified 16-12-2021 05:49
Monarch_02bridge //Date modified 14-12-2021 19:34
Monarch_01 //Date modified 14-12-2021 09:08
Code should look for files whose filename starts with Monarch_ followed by 2 numeric digits and then filter out the recently modified file
So the output should be Monarch_02
I also tried doing
DirectoryInfo dirInfo = new DirectoryInfo(directoryPath);
FileInfo recentlyModLogFile = (from files in dirInfo.GetFiles(Monarch_ + "*") orderby files.LastWriteTime descending select files).First();
//OUtput : Monarch_05bridge
Can someone help me to resolve this issue.
string youngestFile = Directory.GetFiles(directoryPath)
.Where(o => Regexp.Contains(Path.GetFileNameWithoutExtension(o), "Monarch_\\d\\d"))
.OrderByDescending(o => File.GetLastWriteTime(o))
.FirstOrDefault();
This is a quick copy-and-paste from my project files. The Regexp.Contains() is one of the simple methods I wrote to do regexp comparisons.
Notice the Regular Expression I used allow Monarch_02, Monarch_02Bridge and abcMonarch_09 all to be possible result. You can use "^Monarch_\\d\\d$", if you want a strict rule.
Refer to Regular Expressions for details.
private static Match GetFirstMatch(string text, string pattern)
{
Match match = Regex.Match(text, pattern, RegexOptions.None);
return match;
}
public static Boolean Contains(string text, string pattern)
{
return GetFirstMatch(text, pattern).Value != String.Empty;
}
Basically, use Directory.GetFiles(path) to get all the files, then use LINQ to apply conditions, order-bys and fetch the first result.
The Path, Directory and File classes can help a lot when you are working around file system.
So I'm working on a program that will list all the files in a directory. Pretty simple. Basically, when I do this: List<string> dirs = new List<string>(Directory.EnumerateFiles(target));, I don't want it to include the directory and all. Just the file name. When I run my code;
List<string> dirs = new List<string>(Directory.EnumerateFiles(target));
Console.WriteLine($"Folders and files in this directory:\n");
foreach (string i in dirs) {
Console.WriteLine($"> {i}");
}
it gives me the following:
C:\Users\Camden\Desktop\Programming\Visual Studio\C#\DirectoryManager\DirectoryManager\bin\Debug\DirectoryManager.exe
I just want the DirectoryManager.exe part, so I looked it up and I found that you can replace strings inside of strings. Like so: i.Replace(target, "");. However, this isn't doing anything, and it's just running like normal. Why isn't it replacing, and how should I instead do this?
Use methods from the System.IO.Path class.
var fullfile = #"C:\Users\Camden\Desktop\Programming\Visual Studio\C#\DirectoryManager\DirectoryManager\bin\Debug\DirectoryManager.exe";
var fileName = Path.GetFileName(fullfile); // DirectoryManager.exe
var name = Path.GetFileNameWithoutExtension(fullfile); // DirectoryManager
The simplest way is to use the Select IEnumerable extension
(you need to have a using Linq; at the top of your source code file)
List<string> files = new List<string>(Directory.EnumerateFiles(target)
.Select(x => Path.GetFileName(x)));
In this way the sequence of files retrieved by Directory.EnumerateFiles is passed, one by one, to the Select method where each fullfile name (x) is passed to Path.GetFileName to produce a new sequence of just filenames.
This sequence is then returned as a parameter to the List constructor.
And about your question on the Replace method. Remember that the Replace method doesn't change the string that you use to call the method, but returns a new string with the replacement executed. In NET strings are immutable.
So if you want to look at the replacement you need
string justFileName = i.Replace(target, "");
An alternative to using Directory.EnumerateFiles, would be DirectoryInfo.EnumerateFiles. This method returns an IEnumerable<FileInfo>. You can then make use of the FileInfo.Name property of each of the returned objects. Your code would then become:
var files = new DirectoryInfo(target).EnumerateFiles();
Console.WriteLine("Files in this directory:\n");
foreach (FileInfo i in files) {
Console.WriteLine($"> {i.Name}");
}
For just the list of file names:
List<string> fileNames = new DirectoryInfo(target).EnumerateFiles().Select(f => f.Name).ToList();
Alternatively, if you want both files and directories, you can use EnumerateFileSystemInfos. If you need to know if you have a file vs a directory you can query the Attributes property and compare it to the FileAttributes flags enumeration.
var dirsAndFiles = new DirectoryInfo(target).EnumerateFileSystemInfos();
Console.WriteLine("Folders and files in this directory:\n");
foreach (var i in dirsAndFiles) {
var type = (i.Attributes & FileAttributes.Directory) == FileAttributes.Directory ? "Directory" : "File";
Console.WriteLine($"{type} > {i.Name}");
}
The FileSystemInfo.Name property will return either the file's name (in case of a file) or the last directory in the hierarchy (for a directory)--so just the subdirectory name and not the full path ("sub" instead of "c:\sub").
Using Ionic.Zip
I wish to display the files or folders in a specific folder. I am using the SelectEntries method, but it unfortunately is filtering out the folders. Not what I was expecting using '*'.
ICollection<ZipEntry> selectEntries = _zipFile.SelectEntries("*",rootLocation)
If I follow an alternative approach:
IEnumerable<ZipEntry> selectEntries = _zipFile.Entries.Where(e => e.FileName.StartsWith(rootLocation))
I face two problems:
I have to switch '/' for '\' potentially.
I get all the subfolders.
Which is not desirable.
Anyone know why SelectEntries returns no folders, or am I misusing it?
I found a solution in my particular case. I think something about the way the Zipfile was constructed led to it appearing to have folders but none actually existed i.e. the following code yielded an empty list.
_zipFile.Entries.Where(e=>e.IsDirectory).AsList(); // always empty!
I used the following snippet to achieve what I needed. The regex is not as comprehensive as it should be but worked for all cases I needed.
var conformedRootLocation = rootLocation.Replace('\\','/').TrimEnd('/') + "/";
var pattern = string.Format(#"({0})([a-z|A-Z|.|_|0-9|\s]+)/?", conformedRootLocation);
var regex = new Regex(pattern);
return _zipFile.EntryFileNames.Select(e => regex.Match(e))
.Where(match => match.Success)
.Select(match => match.Groups[2].Value)
.Distinct()
.Select(f => new DirectoryResource
{
Name = f, IsDirectory = !Path.HasExtension(f)
})
.ToList();
I am trying to verify if a file exist in a c# console program. The only thing is that the file can have any name.
The only thing that I know is the file extension and there can only be one file of this extension. How can I verify if it exist and then use it whatever the name is?
The problem with using Directory.GetFiles() is that is walks the entire filesystem first, then returns all matches as an array. Even if the very first file examined is the one and only match, it still walks the entire filesystem from the specified root before returning the one match.
Instead, use EnumerateFiles() to do a lazy walk, stopping when the first match is encountered, thus:
DirectoryInfo root = new DirectoryInfo( #"C:\" ) ;
string pattern = "*.DesiredFileExtension" ;
FileInfo desiredFile = root.EnumerateFiles( pattern , SearchOption.AllDirectories )
.First()
;
It will throw an exception if the file's not found. Use FirstOrDefault() to get a null value instead.
Try the Directory.GetFiles static method:
var fileMatches = Directory.GetFiles("folder to start search in", "*.exe", SearchOption.AllDirectories);
if (fileMatches.Length == 1)
{
//my file was found
//fileMatches[0] contains the path to my file
}
Note that with the SearchOption enum you can specify just the current folder or to search recursively.
string extension = "txt";
string dir = #"C:\";
var file = Directory.GetFiles(dir, "*." + extension).FirstOrDefault();
if (file != null)
{
Console.WriteLine(file);
}
If the file does not exist directly under 'dir', you will need to use SearchOption.AllDirectories for Directory.GetFiles
Something like this may work
if (Directory.GetFiles(path, "*.ext").Any())
{
var file = Directory.GetFiles(path, ".ext").First();
}
The code below obviously searches a directory for Files that contain the word "FINAL" but what I'm wondering is can I add to its search criteria? I have a Well_Name and Actual_Date strings that I would like to search for in the File names in addition to the "FINAL" word. Thoughts? Thanks in advance.
DirectoryInfo myDir = new DirectoryInfo("C://DWGs");
var files = myDir.GetFiles("FINAL");
//Can I do something like this to add to my search criteria?
var files = myDir.GetFiles("FINAL" +
drow["Well_Name"].ToString() +
drow["Actual_Date"]);
var files = myDir.GetFileInfo()
.Where(f => f.FileName.Contains("FINAL") ||
f.FileName.Contains(drow["Well_Name"].ToString()) ||
f.FileName.Contains(drow["Actual_Date"]));
Since GetFiles() returns an Enumerable Collection of FileInfo you can just check all of the file names for the criteria that you want.
If you want to get really generic on this you could write a function that looks like this
public IEnumerable<FileInfo> addCriteria(IEnumerable<FileInfo> FileList,
List<String> searchCriteria)
{
var newFileList = FileList;
foreach(String criteria in searchCriteria)
{
newFileList = newFileList.Where(f => f.FileName.Contains(criteria).AsQueryable();
}
return newFileList.AsEnumerable();
}
GetFiles method does not support multiple search criteria, but there is a simple way around this limitation. Run a getFile for each file extension, and then "merge" returned arrays into a List<>. Then use a List's ToArray method to "convert" a List back to an Array.
I used this approach, and it works for me
The code is below (do not forget to reference "using System.Collections.Generic;" namespace):
// Get the DirectoryInfo and FileInfo objects for aspx and html files.
FileInfo[] files_aspx = dir.GetFiles("*.aspx");
FileInfo[] files_html = dir.GetFiles("*.html");
List<FileInfo> files = new List<FileInfo>();
files.AddRange(files_aspx);
files.AddRange(files_html);
files.ToArray();