Resolving relative paths with wildcards in C# - c#

In C#, if I have a directory path and a relative file path with wildcard, e.g.
"c:\foo\bar" and "..\blah\*.cpp"
Is there a simple way to get the list of absolute file paths? e.g.
{ "c:\foo\blah\a.cpp", "c:\foo\blah\b.cpp" }
Background
There is a source code tree, where any directory can contain a build definition file. This file uses relative paths with wildcards to specify a list of source files. The task is to generate a list of absolute paths of all source files for each one of these build definition files.

You can get the absolute path first and then enumerate the files inside the directory matching the wildcard:
// input
string rootDir = #"c:\foo\bar";
string originalPattern = #"..\blah\*.cpp";
// Get directory and file parts of complete relative pattern
string pattern = Path.GetFileName (originalPattern);
string relDir = originalPattern.Substring ( 0, originalPattern.Length - pattern.Length );
// Get absolute path (root+relative)
string absPath = Path.GetFullPath ( Path.Combine ( rootDir ,relDir ) );
// Search files mathing the pattern
string[] files = Directory.GetFiles ( absPath, pattern, SearchOption.TopDirectoryOnly );

It's simple.
using System.IO;
.
.
.
string[] files = Directory.GetFiles(#"c:\", "*.txt", SearchOption.TopDirectoryOnly);

Related

Get the first character from the filename in a filepath

I have an array of filepaths in a directory and I'm trying to move certain files based on alphabet.
string[] filePaths = Directory.GetFiles(#"C:\user\desktop\folder", "*.txt");
foreach (var file in filePaths)
{
if (file.StartsWith("A"))
{
//Move file
The obvious problem is that file.StartWith is pulling the entire filepath (C:\user\desktop\folder\Albert.txt) Which doesn't start with 'A'
So what would be the best way to just target the start of the actual file?
Thanks in advance.
I got it working with Path.GetFileName as per the suggestion by #Jimi
What about this code
var dir = new DirectoryInfo(#"C:\user\desktop\folder");
var files = dir.GetFiles();
foreach (var file in files)
{
if(file.Name.StartsWith("A"))
{
//Move file
You say you're looking to move files by alphabet- if you mean to put files into a folder whose name is the same as the first char of the filename then perhaps:
var desktop = Environment.GetFolderPath(Environment.SpecialFolder.Desktop); //don't hard code the path to the desktop
var root = Path.Combine(desktop, "foldernamehere"); //use path.combine to build paths
foreach(var f in directory.EnumerateFiles(root, "*.txt")){ //prefer EnumerateFiles over GetFiles
var filename = Path.GetFileName(f);
var dest = Path.Combine(root, filename.Remove(1));
Directory.CreateDirectory(dest); //safe to call even if exists, ensures exists
File.Move(f, Path.Combine(dest, filename));
}
See comments for more info
If you have a string that represents a full filename (or directory name), and you want the name without the directory, consider to use Path.GetFileName
string fullFileName = "C:\user\desktop\folder\Albert.txt";
string fileName = Path.GetDirectoryName(fullFileName);
fileName will be "Albert.txt"
With this in mind, your query will be easy:
IEnumerable<string> fullFileNames = ...
char startChar = 'A';
IEnumerable<string> fileNamesThatStartWithStartChar = fullFileNames
.Where(fileName => Path.GetDirectoryName(fileName).StartsWitch(startChar));
In words: from every fileName in the sequence of fullFileName, take the fileName without the directory information. Keep the fileName if this "fileName without directory information" starts with the startChar.
Note: StartsWitch(char) is case sensitive. If you want to check case insensitive, use String.StartsWitch(string, stringComparison)
There's room for improvement!
If you think that there might be a chance that you won't be using all information of all files, consider to use Directory.EnymerateFiles instead of GetFiles. This way, if at the end of your LINQ you decide to use only 3 of the fetched files (or worse: FirstOrDefault(), or Any()), you won't have fetched all files.

Search for file in c#

I wanted to search for files in c# begin with a string.
I followed the code in the internet
string[] dirs = Directory.GetFiles(#"c:\", "c*");
but instead of finding "c", I want to find files contains a string (i mean the file name for example contain.txt and contain.pdf both has "contain") i created. Here is my code
string filetofind;
string[] dirs = Directory.GetFiles(#"c:\", filetofind + "*");
but it just not working, is there anyway else?
If
I want to find files contains a string i created
means you want to check file's content (not name) You have to load the file, e.g. (assuming stringToFind doesn't have line breaks)
string[] dirs = Directory
.EnumerateFiles(#"c:\", "*.txt"); // all txt files (put the right wildcard)
.Where(file => File
.ReadLines(file) // with at least one line
.Any(line => line.Contains(stringToFind))) // which contains stringToFind
.ToArray();
Edit: In case you want files' names which contain c, e.g. "mycode.txt", "Constraints.dat" etc. (but not "demo.com" since c is in the file's extension); you can try *c*.* wild card: file name contains c with any extension:
string[] dirs = Directory
.GetFiles(#"c:\", $"*{filetofind}*.*");
In case of elaborated condition, when standard wildcard in not enough, just add Where:
string[] dirs = Directory
.EnumerateFiles(#"c:\", "*.*")
.Where(path => Your_Condition(Path.GetFileNameWithoutExtension(path)))
.ToArray();
For instance, let's test file name for small (not capital) letter c
string[] dirs = Directory
.EnumerateFiles(#"c:\", "*.*")
.Where(path => Path.GetFileNameWithoutExtension(path).Contains('c'))
.ToArray();
To find files where the file name contains "foo", use
var files = Directory.EnumerateFiles("C:\\dir", "*foo*", SearchOption.AllDirectories);
To find files where the text content contains "foo" use:
var files = Directory.EnumerateFiles("C:\\dir", "*", SearchOption.AllDirectories)
.Where(f => File.ReadAllText(f).Contains("foo"));
This should work, but it will read the entire file as text until you stop enumerating the list of files, so you might want to filter the file list search pattern before reading them. You could also write your own method to inspect each file rather than reading the entire thing into memory for every file.
Substitute SearchOption.AllDirectories for SearchOption.TopDirectoryOnly if you only want to search that directory, and not recursively search subdirectories.
if the file you want find starts with "filetofind" then code is correct. But if "filetofind" comes somewhere between the complete file name then your code must change to
string filetofind;
string[] dirs = Directory.GetFiles(#"c:\", "*filetofind*");

extract particular directories from the set of directories

i have a path dir called serverpath which is configurable.
eg.
serverpath=#"C:\AAA\New folder\";
in server path there are large number of directories. in following format:
serverpath\ID1\ID2\FileType\YYYY\MM\DD.MM.YYYY
i.e. C:\AAA\New folder\123\456\2017\01\01.01.2017
when i call
Directory.EnumerateDirectories(serverpath, "*", System.IO.SearchOption.AllDirectories)
i get all the directories but i want only those path which are in the given format.
so far i have tries adding "??.??.????" pattern in the EnumerateDirectories method
Directory.EnumerateDirectories(serverpath, "??.??.????", System.IO.SearchOption.AllDirectories)
but still i am getting path which are like this:
C:\AAA\New folder\123\456\pdf\2017\01
C:\AAA\New folder\123\456\txt\2017\01
i only want path like these:
C:\AAA\New folder\123\456\pdf\2017\01\01.01.2017
C:\AAA\New folder\123\456\txt\2017\01\01.01.2017
and exclude all the other paths in the directory
any other way to do this other than counting slashes..?
Edit: is there any way to get directory path of the last folder in the directory? "01.01.2017" folders are the last folders in their respective directories.
using System.IO;
using System.Linq;
using System.Text.RegularExpressions;
namespace ConsoleApp
{
class Program
{
static void Main()
{
string serverpath = #"C:\AAA\New folder\";
Regex re = new Regex(#"\d{2}\.\d{2}\.\d{4}");
var dirs = from dir in
Directory.EnumerateDirectories(serverpath, "*", SearchOption.AllDirectories)
where re.IsMatch(dir)
select dir;
}
}
}
This seems to work. Sorry if I have misunderstood - I am new to this.
\d = digit
{} = quantifier (of what is left of the quantifier)
. = any character (NOT OF ANY USE HERE)
\. = explicit dot

EnumerateFiles vs EnumerateDirectories searchPattern

I've come across one thing.
There is code:
var searchPattern = #"??????";
var path = "C:\Users\MyUser\Folder";
IEnumerable<string> file = Directory.EnumerateFiles(path, searchPattern);
IEnumerable<string> dir = Directory.EnumerateDirectories(path, searchPattern);
and lets say following directories and files:
a.txt
b.txt
a
b
According to Documentation there "?" char should represent zero or one character in that position. Therefore I expect dir containing a and b and file should be a.txt and b.txt.
However my file variable contains only empty collection.
Why is that?

Regex to parse out filename and partial path, conditionally

I have a C# app that uses the search functions to find all files in a directory, then shows them in a list. I need to be able to filter the files based on extension (possible using the search function) and directory (eg, block any in the "test" or "debug" directories from showing up).
My current code is something like:
Regex filter = new Regex(#"^docs\(?!debug\)(?'display'.*)\.(txt|rtf)");
String[] filelist = Directory.GetFiles("docs\\", "*", SearchOption.AllDirectories);
foreach ( String file in filelist )
{
Match m = filter.Match(file);
if ( m.Success )
{
listControl.Items.Add(m.Groups["display"]);
}
}
(that's somewhat simplified and consolidated, the actual regex is created from a string read from a file and I do more error checking in between.)
I need to be able to pick out a section (usually a relative path and filename) to be used as the display name, while ignoring any files with a particular foldername as a section of their path. For example, for these files, only ones with +s should match:
+ docs\info.txt
- docs\data.dat
- docs\debug\info.txt
+ docs\world\info.txt
+ docs\world\pictures.rtf
- docs\world\debug\symbols.rtf
My regex works for most of those, except I'm not sure how to make it fail on the last file. Any suggestions on how to make this work?
Try Directory.GetFiles. This should do what you want.
Example:
// Only get files that end in ".txt"
string[] dirs = Directory.GetFiles(#"c:\", "*.txt", SearchOption.AllDirectories);
Console.WriteLine("The number of files ending with .txt is {0}.", dirs.Length);
foreach (string dir in dirs)
{
Console.WriteLine(dir);
}
^docs\\(?:(?!\bdebug\\).)*\.(?:txt|rtf)$
will match a string that
starts with docs\,
does not contain debug\ anywhere (the \b anchor ensures that we match debug as an entire word), and
ends with .txt or .rtf.

Categories