Reputation: 2861
I have a C# console app which gets all files in a directory. Taking the file name below as an example, and given that I will have 3 strings, ref, year1, year2, how could I say:
File name: 31596_2015-06-30.pdf
Give me all files where the file name contain ref AND file name contains a year between year1 and year 2? Code so far:
var files = Directory.EnumerateFiles(sourceDir, "*", SearchOption.TopDirectoryOnly)
.Select(Path.GetFileName);
string start_year = null;
string end_year = null;
string ref = null;
// dr is a sql data reader
if (dr.HasRows == true)
{
while (dr.Read())
{
start_year = dr.GetString(1).Substring(7, 4);
end_year = dr.GetString(2).Substring(7, 4);
ref = dr.GetString(3);
foreach(string filename in files)
{
if (filename.Contains(ref))
{
File.Copy(sourceDir + filename, targetDir + filename);
}
}
File.Copy(sourceDir + dr.GetString(0), targetDir + dr.GetString(0));
}
}
Upvotes: 2
Views: 751
Reputation: 23732
Assuming that your filenames have always the format as in your post, you first need to split the year out of the name. One possible solution could be:
string filenameYear = filename.Split('_')[1].Split('-')[0];
then you can use this string in your if condition to ask for all three cases:
if (filename.Contains(_ref) &&
Convert.ToInt32(filenameYear) > Convert.ToInt32(start_year) &&
Convert.ToInt32(filenameYear) < Convert.ToInt32(end_year))
{
// Do what ever you desire
}
in the line:
File.Copy(sourceDir + filename, targetDir + filename);
If sourceDir
and targetDir
has not a \
in the end or filename
in the beginning. This will crash.
You can use
File.Copy(Path.Combine(sourceDir,filename), Path.combine(targetDir, filename);
to avoid problems
ps. you should avoid using ref
as a name for variables in C#.
it is reserved as a keyword
Upvotes: 2
Reputation: 186823
I suggest extracting a class, say, FileData
:
public class FileData {
public bool IsParsed {get; private set; }
public String FileName {get; private set; }
public DateTime Date {get; private set; }
public String Ref {get; private set; }
public FileData(String path) {
FileName = path;
if (String.IsNullOrEmpty(path))
return;
int p = path.IndexOf('_');
if (p < 0)
return;
Ref = path.Substring(0, p);
DateTime dt;
IsParsed = DateTime.TryParseExact(path.Substring(p + 1),
"yyyy-MM-dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out dt);
Date = dt;
}
}
By doing this you can put a simple Linq to obtain the files
var files = Directory
.EnumerateFiles(sourceDir, "*", SearchOption.TopDirectoryOnly)
.Select(file => new FileData(file))
.Where(info => info.IsParsed)
.Where(info => String.Equals(info.Ref, myRef))
.Where(info => info.Date.Year >= year1 && info.Date.Year <= year2)
.Select(info => info.FileName);
Upvotes: 3
Reputation: 56
I like Linq for this sort of thing. Unless you know for a fact that the values in the reader will always by what you expect, you should perform some validations, but this will achieve your stated goal with the least amount of changes to your sample code.
var start_year = (DateTime)dr.GetString(1).Substring(7, 4);
var end_year = (DateTime)dr.GetString(2).Substring(7, 4);
ref = dr.GetString(3);
foreach(string filename in files.Where(x => x.StartsWith(ref)
&& (DateTime)x.Substring(7, 4) >= start_year
&& (DateTime)x.Substring(7, 4) <= end_year))
{
File.Copy(sourceDir + filename, targetDir + filename);
}
Upvotes: 1