I have 4 text files in one folder and a pattern.txt to compare these text files..In pattern.txt i have
insert
update
delete
drop
I need to compare this text file with those four text files and if these patterns matches any line in that text files i have to write those lines in another log file...i had read those files using linq..i need to compare those files and write in a text file with line number..here is my code
var foldercontent = Directory.GetFiles(pathA)
.Select(filename => File.ReadAllText(filename))
.Aggregate(new StringBuilder(),
(sb, s) => sb.Append(s).Append(Environment.NewLine),
sb => sb.ToString());
var pattern = File.ReadAllLines(pathB).Aggregate(new StringBuilder(),
(sb, s) => sb.Append(s).Append(Environment.NewLine),
sb => sb.ToString());
using (var dest = File.AppendText(Path.Combine(_logFolderPath, "log.txt")))
{
//dest.WriteLine("LineNo : " + counter.ToString() + " : " + "" + line);
}
EDIT
I have already used c# to compare two text files but i need this in linq
while ((line = file.ReadLine()) != null)
{
if (line.IndexOf(line2, StringComparison.CurrentCultureIgnoreCase) != -1)
{
dest.WriteLine("LineNo : " + counter.ToString() + " : " + " " + line.TrimStart());
}
counter++;
}
file.BaseStream.Seek(0, SeekOrigin.Begin);
counter = 1;
There might be a simpler solution, but this is at least working if you really want to use LINQ:
var foldercontent = Directory.GetFiles(pathA)
.Select(filename => new
{
Filename = filename,
Lines = File.ReadAllLines(filename)
})
.SelectMany(file => file.Lines.Select((line, idx) => new
{
LineNumber = idx + 1,
Text = line,
FileName = file.Filename
}));
var pattern = File.ReadAllLines(pathB);
var result = from fileLine in foldercontent
where pattern.Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1)
select fileLine;
foreach (var match in result)
{
System.Diagnostics.Debug.WriteLine("File: {0} LineNo: {1}: Text: {2}", match.FileName, match.LineNumber, match.Text);
}
Or if you want, you can combine that into one LINQ query (but thats not very readable i think):
var result = from fileLine in (Directory.GetFiles(pathA)
.Select(filename => new
{
Filename = filename,
Lines = File.ReadAllLines(filename)
})
.SelectMany(file => file.Lines.Select((line, idx) => new
{
LineNumber = idx + 1,
Text = line,
FileName = file.Filename
})))
where File.ReadAllLines(pathB).Any(p => fileLine.Text.IndexOf(p, StringComparison.CurrentCultureIgnoreCase) != -1)
select fileLine;
Since I'm a linq enthusiast, and will sometimes use a tool when it's inappropriate (I agree with #juharr about using grep or something similar for this situation) here is a possible version for you.
static IEnumerable<string> CreateMatchesLog(string patternFilePath, string pathToSearch)
{
string logTemplate = "File {0}, Line: {1}, Pattern: {2}";
DirectoryInfo di = new DirectoryInfo(pathToSearch);
var patternlines = File.ReadAllLines(patternFilePath);
var fileslines = di.EnumerateFiles().Select(fi => File.ReadAllLines(fi.FullName).Select((line, i) => new {fi.FullName, line, i}));
return from filelines in fileslines
from pattern in patternlines
from fileline in filelines
where fileline.line.Contains(pattern)
select String.Format(logTemplate, fileline.FullName, fileline.i + 1, pattern);
}
Then you'd write the output of this function to a file.
using (StreamWriter sw = new StreamWriter("log.txt", true))
{
foreach (var log in CreateMatchesLog("pattern.txt", #"c:\test"))
{
sw.WriteLine(log);
}
}
I've set append to true in the StreamWriter, because I assume you don't want to lose the contents of the file each time you run the programme.
It looks pretty inefficient (not tested that aspect), but it uses linq and lambdas up the wazoo!
Related
I would like to read from a text file in the Internet the certain assignment to a word.
In the output "content" I get the complete content of the text file.
But I only want v7.7.3 from the line: version = "v7.7.3".
How can I filter by version with the streamreader?
That is the LastVersion.txt file:
[general]
version = "v7.7.3"
messagenew = "Works with June 2018 Update!\n Plus new Smart Farm strategy\n New Siege Machines\n For more information, go to \n https://mybot.run \n Always free and open source."
messageold = "A new version of MyBot (v7.7.3) is available!\nPlease download the latest from:\nhttps://mybot.run"
Updated: That's my current code.
public string myBotNewVersionURL = "https://raw.githubusercontent.com/MyBotRun/MyBot/master/LastVersion.txt";
public string myBotDownloadURL = null;
public string userDownloadFolder = #"C:\Users\XXX\Download\";
public string newMyBotVersion = null;
public string currentMyBotVersion = null;
public string currentMyBotFileName = null;
public string currentMyBotPath = null;
public void Btn_checkUpdate_Click(object sender, EventArgs e)
{
OpenFileDialog openCurrentMyBot = new OpenFileDialog();
openCurrentMyBot.Title = "Choose MyBot.run.exe";
openCurrentMyBot.Filter = "Application file|*.exe";
openCurrentMyBot.InitialDirectory = userDownloadFolder;
if (openCurrentMyBot.ShowDialog() == DialogResult.OK)
{
MyBot_set.SetValue("mybot_path", Path.GetDirectoryName(openCurrentMyBot.FileName));
MyBot_set.SetValue("mybot_exe", Path.GetFullPath(openCurrentMyBot.FileName));
string latestMyBotPath = Path.GetFullPath(openCurrentMyBot.FileName);
var latestMyBotVersionInfo = FileVersionInfo.GetVersionInfo(latestMyBotPath);
currentMyBotVersion = "v" + latestMyBotVersionInfo.FileVersion;
MyBot_set.SetValue("mybot_version", currentMyBotVersion);
WebClient myBotNewVersionClient = new WebClient();
Stream stream = myBotNewVersionClient.OpenRead(myBotNewVersionURL);
StreamReader reader = new StreamReader(stream);
String content = reader.ReadToEnd();
var sb = new StringBuilder(content.Length);
foreach (char i in content)
{
if (i == '\n')
{
sb.Append(Environment.NewLine);
}
else if (i != '\r' && i != '\t')
sb.Append(i);
}
content = sb.ToString();
var vals = content.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
)
.SkipWhile(line => !line.StartsWith("[general]"))
.Skip(1)
.Take(1)
.Select(line => new
{
Key = line.Substring(0, line.IndexOf('=')),
Value = line.Substring(line.IndexOf('=') + 1).Replace("\"", "").Replace(" ", "")
});
newMyBotVersion = vals.FirstOrDefault().Value;
}
Read From local
var vals = File.ReadLines("..\\..\\test.ini")
.SkipWhile(line => !line.StartsWith("[general]"))
.Skip(1)
.Take(1)
.Select(line => new
{
Key = line.Substring(0, line.IndexOf('=')),
Value = line.Substring(line.IndexOf('=') + 1)
});
Console.WriteLine("Key : " + vals.FirstOrDefault().Key +
" Value : " + vals.FirstOrDefault().Value);
Updated
for read from Git , File.ReadLines not work with URL.
string myBotNewVersionURL = "https://raw.githubusercontent.com/MyBotRun/MyBot/master/LastVersion.txt";
WebClient myBotNewVersionClient = new WebClient();
Stream stream = myBotNewVersionClient.OpenRead(myBotNewVersionURL);
StreamReader reader = new StreamReader(stream);
String content = reader.ReadToEnd();
var sb = new StringBuilder(content.Length);
foreach (char i in content)
{
if (i == '\n')
{
sb.Append(Environment.NewLine);
}
else if (i != '\r' && i != '\t')
sb.Append(i);
}
content = sb.ToString();
var vals = content.Split(
new[] { Environment.NewLine },
StringSplitOptions.None
)
.SkipWhile(line => !line.StartsWith("[general]"))
.Skip(1)
.Take(1)
.Select(line => new
{
Key = line.Substring(0, line.IndexOf('=')),
Value = line.Substring(line.IndexOf('=') + 1)
});
Console.WriteLine("Key : " + vals.FirstOrDefault().Key + " Value : " + vals.FirstOrDefault().Value);
I want to plot a graph from .csv file using second and fourth columns.
The data starts from the 9th row, I could skip 8 lines. But I want to access specific columns for plotting graph.
string ChosenFile = "";
if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
{
ChosenFile = openFileDialog1.FileName;
char delimited = ',';
if (new FileInfo(ChosenFile).Length != 0)
{
try
{
var data = File.ReadLines(#ChosenFile).Skip(8)
.Select(line => line.Split(new Char[] { delimited }, StringSplitOptions.RemoveEmptyEntries))
.Select(chunk => chunk
.Select(x => Double.Parse(x, CultureInfo.InvariantCulture))
.ToArray());
series.Points.Clear();
foreach (var pair in data)
{
series.Points.AddXY(pair[0], pair[1]);
}
}
catch
{
logger.info("The file " + openFileDialog1.FileName + " cannot be opened because the content may be invalid or damaged.");
}
}
else logger.info(openFileDialog1.FileName + " is an empty file.");
}
This LINQ statement accesses only first two columns, but for my application I need to access data from second and fourth columns
What changes do I need to make in this statement to get these columns?
First let's fix your issue. Every column are in your data, you can access them by the index.
char delimited = ',';
var inputCSV = #"Skip it
Skip ita
Skip it
Col1,Col2,Foo,Bar
2.3,0.2,3.0,40.5
2.3,0.2,3.0,40.5
2.3,0.2,3.0,40.5";
var fileReadLinesMimic = inputCSV
.Split(new[] { Environment.NewLine }, StringSplitOptions.None);
var data = fileReadLinesMimic
.Skip(4)
.Select(line => line.Split(new Char[] { delimited }, StringSplitOptions.RemoveEmptyEntries))
.Select(chunk =>
chunk.Select(x => Double.Parse(x, CultureInfo.InvariantCulture)
)
.ToArray());
foreach (var item in data)
{
Console.WriteLine($"Col1={item[0]}; Col2={item[1]}; Foo={item[2]}; Bar={item[3]};");
}
I have this function:
var dupeFiles = Directory.EnumerateFiles(strPath, "*", SearchOption.AllDirectories)
.Select(fullPath => new
{
Name = Path.GetFileName(fullPath),
FullPath = fullPath
})
.GroupBy(file => file.Name)
.Where(fileGroup => fileGroup.Count() > 1);
foreach (var dupeGroup in dupeFiles)
{
using (System.IO.StreamWriter file =
new System.IO.StreamWriter(#"DupeFiles.txt", true))
{
file.WriteLine(dupeGroup.Key);
}
foreach (var dupeFile in dupeGroup)
{
using (System.IO.StreamWriter file =
new System.IO.StreamWriter(#"DupeFiles.txt", true))
{
file.WriteLine($" {dupeFile.FullPath}");
}
}
}
But im getting this result:
FILE.TXT
...\RootFolder\Folder1\Child1\AnotherChild\FILE.TXT
...\RootFolder\Folder1\Child2\AnotherChild\FILE.TXT
...\RootFolder\Folder1\Child3\FILE.TXT
...\RootFolder\Folder2\Child3\FILE.TXT
...\RootFolder\Folder2\Child2\AnotherChild\FILE.TXT
How limit the result for the same file path from folder1 and folder2 (or more, this same child level)? In that case, i just want the results:
FILE.TXT
...\RootFolder\Folder1\Child2\AnotherChild\FILE.TXT
...\RootFolder\Folder2\Child2\AnotherChild\FILE.TXT
Thank you!
Thank you all replys, but it stills don't helps. Maybe i can't tell you what exactly i need, so look those real pic:
As you can see, the first file: NMS_REALITY_GCTECHNOLOGYTABLE.MBIN are repeated on 3 folders:
LessOverHeat10 ...
Reduced Launch Cost...
_BettterFreighter...
Thats all right, because as you can see, the same file was on (root) folders different.
But another other files, PLANTINTERACTION.ENTITY.MBIN, repeats on a lot of others folders, but inside the same folder:
_FASTER_FARMING_X50.
This part is wrong. I would lik to ignore (not list) all those files, because its for the same folder. I just would like to list, or mark them as conflicted, if its at the same path, but for different root folder.
Its better now? Thank you so much, sorry if can't explain right my needs.
Count on you, thanks!!!
Make a ParentPath attribute and group by that then select what you want from every parentDirectory by skipping all you don't want.
var dupeFiles = Directory.EnumerateFiles(strPath, "*", SearchOption.AllDirectories)
.Select(fullPath => new
{
Name = Path.GetFileName(fullPath),
FullPath = fullPath,
ParentPath = GetParentPath(fullPath)
}).GroupBy(file => file.ParentPath)
.Select(parentDirectory => parentDirectory
.SkipWhile((childFile, index) => index != 1)
.First()
);
StreamWriter fileWriter = new StreamWriter(#"DupeFiles.txt", true);
foreach(var aFile in dupeFiles.ToList())
Console.WriteLine(aFile.FullPath);
...
private string GetParentPath(string fullPath)
{
string [] strArr = fullPath.Split('\\');
string parentPath = strArr[0] + '\\' + strArr[1] + '\\' + strArr[2] + '\\' + strArr[3] + '\\' + strArr[4] + '\\' + strArr[5];
//Console.WriteLine("parentPath: " + parentPath);
return parentPath;
}
...
Edited answer using double foreach and retaining IGrouping.Key
string strPath = "C:\\Users\\Luke\\Desktop\\RootFolder";
var dupeFiles = Directory.EnumerateFiles(strPath, "*", SearchOption.AllDirectories)
.Select(fullPath => new
{
Name = Path.GetFileName(fullPath),
FullPath = fullPath,
}).GroupBy(file => GetParentPath(file.FullPath))
.Select(parentDirectory =>
parentDirectory.SkipWhile((childFile, index) => index != 1).First()
).GroupBy(file => file.Name, file => file.FullPath);
foreach(var dupeGroup in dupeFiles)
{
Console.WriteLine("key is: " + dupeGroup.Key);
foreach (var dupeFile in dupeGroup)
{
Console.WriteLine(dupeFile);
}
}
/*example output
key is: FILE.txt
C:\Users\Luke\Desktop\RootFolder\Folder1\Child2\AnotherChild\FILE.txt
C:\Users\Luke\Desktop\RootFolder\Folder2\Child2\AnotherChild\FILE.txt
*/
FileInfo[] folderFiles = folder.GetFiles();
foreach (FileInfo file in folderFiles)
{
int fileCount = 0;
StreamWriter sw = null;
string fileName = Path.GetFileNameWithoutExtension(file.Name);
string[] brkedfilename = fileName.Split('_');
string stringToCheck = brkedfilename[3];
for (int i = 0; i <= folderFiles.Count() - 1; i++)
{
string fileName2 = folderFiles[i].Name;
string[] brkedfilename2 = fileName2.Split('_');
if (brkedfilename2[3] == stringToCheck)
{
fileCount = ++fileCount;
if (fileCount == 2)
{
sw = new StreamWriter(folderPath + "/" + newFileName, true);
sw.WriteLine(stringToCheck + " " + "--" + " " + "Repeated in folder " + " " + folder.Name);
sw.Close();
}
}
}
}
By doing this way, if a file name is existing 2 times , it is writing that file name 2 times. But I want it to write only once.
Any help would be appreciated. Thanks in advance. :)
You can use LINQ to find files with same brkedNames:
var repeatedFiles = from f in folderFiles
let brkedName = Path.GetFileNameWithoutExtension(f.Name).Split('_')[3]
group f by brkedName into g
where g.Count() > 1
select new
{
BrkedName = g.Key,
Count = g.Count(),
Files = g
};
This query groups all files by 4th part of splitted names (note: as in your original code I don't check if there is at least 4 parts) and then select groups with more than one file. It also provides some stats - brked name, count of files with same name and files collection.
foreach(var group in repeatedFiles)
sw.WriteLine($"{group.BrkedName} -- repeated {group.Count} times in {folder.Name}");
You can use Dictionary ( filename, repeat time) to list all filename exist. And after that you can loop the dictionary to write to console.
I propose use a hashset. Hashset cannot contain duplicate elements. When You add duplicate element do hashset method Add return false and program go on witout error but hashset will not take duplicate element
var duplicate = new HashSet<string>();
foreach (FileInfo file in folderFiles)
{
int fileCount = 0;
StreamWriter sw = null;
string fileName = Path.GetFileNameWithoutExtension(file.Name);
string[] brkedfilename = fileName.Split('_');
string stringToCheck = brkedfilename[3];
if (!duplicate.Add(stringToCheck))
{
sw = new StreamWriter(folderPath + "/" + newFileName, true);
sw.WriteLine(stringToCheck + " " + "--" + " " + "Repeated in folder " + " " + folder.Name);
sw.Close();
}
}
Program adds each element do Hashset duplicate when element is in Hashset already Add metod return false when I know the element is in the Hashset and I save in the file as You want
I have a folder that is filled with dwg files so I just need to find the latest version of a File or if a File has no versions then copy it to a directory. For example here are three files:
ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg
ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg
Notice the difference is one file has a _1 and another has a _2 so the latest file here is the _2. I need to keep the latest file and copy it to a directory. Some files will not have different versions so those can be copied. I cannot focus on the creation date of the file or the modified date because in many instances they are the same so all I have to go on is the file name itself. I'm sure there is a more efficient way to do this than what I will post below.
DirectoryInfo myDir = new DirectoryInfo(#"H:\Temp\Test");
var Files = myDir.GetFiles("*.dwg");
string[] fileList = Directory.GetFiles(#"H:\Temp\Test", "*FINAL*", SearchOption.AllDirectories);
ArrayList list = new ArrayList();
ArrayList WithUnderscores = new ArrayList();
string nameNOunderscores = "";
for (int i = 0; i < fileList.Length; i++)
{
//Try to get just the filename..
string filename = fileList[i].Split('.')[0];
int position = filename.LastIndexOf('\\');
filename = filename.Substring(position + 1);
filename = filename.Split('_')[0];
foreach (FileInfo allfiles in Files)
{
var withoutunderscore = allfiles.Name.Split('_')[0];
withoutunderscore = withoutunderscore.Split('.')[0];
if (withoutunderscore.Equals(filename))
{
nameNOunderscores = filename;
list.Add(allfiles.Name);
}
}
//If there is a number after the _ then capture it in an ArrayList
if (list.Count > 0)
{
foreach (string nam in list)
{
if (nam.Contains("_"))
{
//need regex to grab numeric value after _
var match = new Regex("_(?<number>[0-9]+)").Match(nam);
if (match.Success)
{
var value = match.Groups["number"].Value;
var number = Int32.Parse(value);
WithUnderscores.Add(number);
}
}
}
int removedcount = 0;
//Whats the max value?
if (WithUnderscores.Count > 0)
{
var maxval = GetMaxValue(WithUnderscores);
Int32 intmax = Convert.ToInt32(maxval);
foreach (FileInfo deletefile in Files)
{
string shorten = deletefile.Name.Split('.')[0];
shorten = shorten.Split('_')[0];
if (shorten == nameNOunderscores && deletefile.Name != nameNOunderscores + "_" + intmax + ".dwg")
{
//Keep track of count of Files that are no good to us so we can iterate to next set of files
removedcount = removedcount + 1;
}
else
{
//Copy the "Good" file to a seperate directory
File.Copy(#"H:\Temp\Test\" + deletefile.Name, #"H:\Temp\AllFinals\" + deletefile.Name, true);
}
}
WithUnderscores.Clear();
list.Clear();
}
i = i + removedcount;
}
else
{
//This File had no versions so it is good to be copied to the "Good" directory
File.Copy(#"H:\Temp\SH_Plats\" + filename, #"H:\Temp\AllFinals" + filename, true);
i = i + 1;
}
}
I've made a Regex based solution, and apparently come late to the party in the meantime.
(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg
this regex will recognise the fileName and version and split them into groups, a pretty simple foreach loop to get the most recent files in a dictionary (cos I'm lazy) and then you just need to put the fileNames back together again before you access them.
var fileName = file.Key + "_" + file.Value + ".dwg"
full code
var files = new[] {
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012.dwg",
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012_1.dwg",
"ABBIE 08-10 #6-09H4 FINAL 06-12-2012_2.dwg",
"Second File.dwg",
"Second File_1.dwg",
"Third File.dwg"
};
// regex to split fileName from version
var r = new Regex( #"(?<fileName>[A-Za-z0-9-# ]*)_?(?<version>[0-9]+)?\.dwg" );
var latestFiles = new Dictionary<string, int>();
foreach (var f in files)
{
var parsedFileName = r.Match( f );
var fileName = parsedFileName.Groups["fileName"].Value;
var version = parsedFileName.Groups["version"].Success ? int.Parse( parsedFileName.Groups["version"].Value ) : 0;
if( latestFiles.ContainsKey( fileName ) && version > latestFiles[fileName] )
{
// replace if this file has a newer version
latestFiles[fileName] = version;
}
else
{
// add all newly found filenames
latestFiles.Add( fileName, version );
}
}
// open all most recent files
foreach (var file in latestFiles)
{
var fileToCopy = File.Open( file.Key + "_" + file.Value + ".dwg" );
// ...
}
You can use this Linq query with Enumerable.GroupBy which should work(now tested):
var allFiles = Directory.EnumerateFiles(sourceDir, "*.dwg")
.Select(path => new
{
Path = path,
FileName = Path.GetFileName(path),
FileNameWithoutExtension = Path.GetFileNameWithoutExtension(path),
VersionStartIndex = Path.GetFileNameWithoutExtension(path).LastIndexOf('_')
})
.Select(x => new
{
x.Path,
x.FileName,
IsVersionFile = x.VersionStartIndex != -1,
Version = x.VersionStartIndex == -1 ? new Nullable<int>()
: x.FileNameWithoutExtension.Substring(x.VersionStartIndex + 1).TryGetInt(),
NameWithoutVersion = x.VersionStartIndex == -1 ? x.FileName
: x.FileName.Substring(0, x.VersionStartIndex)
})
.OrderByDescending(x => x.Version)
.GroupBy(x => x.NameWithoutVersion)
.Select(g => g.First());
foreach (var file in allFiles)
{
string oldPath = Path.Combine(sourceDir, file.FileName);
string newPath;
if (file.IsVersionFile && file.Version.HasValue)
newPath = Path.Combine(versionPath, file.FileName);
else
newPath = Path.Combine(noVersionPath, file.FileName);
File.Copy(oldPath, newPath, true);
}
Here's the extension method which i'm using to determine if a string is parsable to int:
public static int? TryGetInt(this string item)
{
int i;
bool success = int.TryParse(item, out i);
return success ? (int?)i : (int?)null;
}
Note that i'm not using regex but string methods only.
Try this
var files = new My.Computer().FileSystem.GetFiles(#"c:\to\the\sample\directory", Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg");
foreach (String f in files) {
Console.WriteLine(f);
};
NB: Add a reference to Microsoft.VisualBasic and use the following line at the beginning of the class:
using My = Microsoft.VisualBasic.Devices;
UPDATE
The working sample[tested]:
String dPath=#"C:\to\the\sample\directory";
var xfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, "*.dwg").Where(c => Regex.IsMatch(c,#"\d{3,}\.dwg$"));
XElement filez = new XElement("filez");
foreach (String f in xfiles)
{
var yfiles = new My.Computer().FileSystem.GetFiles(dPath, Microsoft.VisualBasic.FileIO.SearchOption.SearchAllSubDirectories, string.Format("{0}*.dwg",System.IO.Path.GetFileNameWithoutExtension(f))).Where(c => Regex.IsMatch(c, #"_\d+\.dwg$"));
if (yfiles.Count() > 0)
{
filez.Add(new XElement("file", yfiles.Last()));
}
else {
filez.Add(new XElement("file", f));
};
};
Console.Write(filez);
Can you do this by string sort? The only tricky part I see here is to convert the file name to a sortable format. Just do a string replace from dd-mm-yyyy to yyyymmdd. Then, sort the the list and get the last record out.
This is what you want considering fileList contain all file names
List<string> latestFiles=new List<string>();
foreach(var groups in fileList.GroupBy(x=>Regex.Replace(x,#"(_\d+\.dwg$|\.dwg$)","")))
{
latestFiles.Add(groups.OrderBy(s=>Regex.Match(s,#"\d+(?=\.dwg$)").Value==""?0:int.Parse(Regex.Match(s,#"\d+(?=\.dwg$)").Value)).Last());
}
latestFiles has the list of all new files..
If fileList is bigger,use Threading or PLinq