I'm having a bit of trouble passing this parameter to a class i have. Does anybody have any ideas?
Class 1's code:
public void DriveRecursion(string retPath)
{
//recurse through files. Let user press 'ok' to move onto next step
// string[] files = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
//string replacement = "";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
filePath.Add(fileNames);
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = fileNameOnly;
dataGridView1.Rows.Add(dgr);
\\I want to pass fileNames to my FileCleanup Method
\\I tried this:
\\SanitizeFileNames sf = new SanitizeFileNames();
\\sf.Add(fileNames); <-- this always gets an error..plus it is not an action i could find in intellisense
}
else
{
continue;
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
Class 2's code:
public class SanitizeFileNames
{
public void FileCleanup(string fileNames)
{
string regPattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = "";
Regex regExPattern = new Regex(regPattern);
}
What i want to do in SanitizeFileNames is do a foreach through the FileNames & FilePath and replace invalid chars (as defined in my Regex pattern). So, something along the lines of this:
using (StreamWriter sw = new StreamWriter(#"S:\File_Renames.txt"))
{
//Sanitize and remove invalid chars
foreach (string Files2 in filePath)
{
try
{
string filenameOnly = Path.GetFileName(Files2);
string pathOnly = Path.GetDirectoryName(Files2);
string sanitizedFilename = regEx.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFilename);
sw.Write(sanitized + "\r\n");
System.IO.File.Move(Files2, sanitized);
}
//error logging
catch(Exception ex)
{
StreamWriter sw2 = new StreamWriter(#"S:\Error_Log.txt");
sw2.Write("ERROR LOG");
sw2.WriteLine(DateTime.Now.ToString() + ex + "\r\n");
sw2.Flush();
sw2.Close();
}
}
}
However, I'm having trouble passing the fileNames into my SanitizeFileNames class. Can anybody help me?
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
if (regEx.IsMatch(fileNames))
{
string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
filePath.Add(fileNames);
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = fileNameOnly;
dataGridView1.Rows.Add(dgr);
new SanitizeFileNames().FileCleanup(fileNames);
}
else
{
continue;
}
}
}
I suppose you want to pass a dirty name to the FileCleanup function and get a clean out. Here is how you can do that :
public String FileCleanup(string fileNames)
{
string regPattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = "";
Regex regExPattern = new Regex(regPattern);
...
return cleanName;
}
and use it in your code like this:
String cleanName = new SanitizeFileNames().FileCleanup(fileNames);
where you put the comment.
You can create a third class static class and add static variable called files “public static List<string> Files= new List<string>()” as example.
When you create the files add the same files to the static variable.
When you clean the files loop throw the static variable, and at the end clear it.
The parameter type should be an enumerable collection of some sort: a list or an array would do. Also, strings are immutable so you could return a list of cleaned up filenames:
public class SanitizeFilenames
{
public List<string> FileCleanUp(IEnumerable<string> filenames)
{
var cleanedFileNames = new List<string>();
var invalidChars = Path.GetInvalidFileNameChars();
foreach(string file in filenames)
{
if(file.IndexOfAny(invalidChars) != -1)
{
// clean the file name and add it to the cleanedFileNames list
}
else
{
// nothing to clean here
cleanedFileNames.Add(file);
}
}
return cleanedFileNames;
}
}
Related
Using user input into a textbox, I want to search for which file in the directory contains that text. I would then like to parse out the information
but I can't seem to find the string or at least return the information. Any help would be greatly appreciated.
My current code:
private void btnSearchSerial_Click(object sender, EventArgs e)
{
dynamic dirScanner = #"\\mypath\";
string strSerial;
string strSID;
string strInputLine;
string strOutput;
strSerial = Convert.ToString(txtSerialSearch);
strSID = Convert.ToString(txtSID);
if (txtSerialSearch.Text != "" && txtSID.Text != "")
{
try
{
string[] allFiles = Directory.GetFiles(dirScanner);
foreach (string file in allFiles)
{
if (file.EndsWith(".txt"))
{
using (StreamReader sr = new StreamReader(file))
{
while (sr.Peek() >= 0)
{
strInputLine = sr.ReadLine();
if (strInputLine.Contains(strSerial))
{
strOutput = Convert.ToString(strInputLine);
lblOutput.Text = Convert.ToString(strOutput);
}
}
}
}
}
}
}
}
You seem quite lost. Why are you using a dynamic when a string is all that you need? Your code has too many unnecessary variables and convertions. Here's a much simpler way to do it. I don't know what you want the label to have if there are many matching lines, here I'm only placing the first one there:
string dirScanner = #"\\mypath\";
if (string.IsNullOrWhiteSpace(txtSerialSearch.Text) || string.IsNullOrWhiteSpace(txtSID.Text))
return;
string[] allFiles = Directory.GetFiles(dirScanner, "*.txt");
foreach (string file in allFiles)
{
string[] lines = File.ReadAllLines(file);
string firstOccurrence = lines.FirstOrDefault(l => l.Contains(txtSerialSearch.Text));
if (firstOccurrence != null)
{
lblOutput.Text = firstOccurrence;
break;
}
}
I have implemented the same using Regular Expressions. You need to use namespace using System.Text.RegularExpressions;
string strSerial = #"Microsoft";
Regex match = new Regex(strSerial);
string matchinglines = string.Empty;
List<string> filenames = new List<string>(Directory.GetFiles(textBox1.Text));
foreach(string filename in filenames)
{
//StreamReader strFile = new StreamReader(filename);
string fileContent = File.ReadAllText(filename);
if(match.IsMatch(fileContent))
{
label1.Text = Regex.Match(fileContent, strSerial).ToString();
break;
}
}
Use System.LINQ:
var list_of_files_that_match = Directory.EnumerateFiles(dir).Where(delegate (string t)
{
return System.IO.File.ReadAllText(t).Contains(your_text);
}).ToList();
This worked for me. Quick and simple.
within my Csv File i have a column which holds a string and a datetime type. i would like to separate these data in two columns, one column which holds the string and one which holds the date but converts the datetime type as a string too.
After doing some research i noticed that i could use the string.split function which will add a comma after the three character which are TIP and then push the date in a new column. however i do not know to code this process
class Program
{
static void Main(string[] args)
{
string currentDirectory = Directory.GetCurrentDirectory();
DirectoryInfo directory = new DirectoryInfo(currentDirectory);
var fileName = Path.Combine(directory.FullName, "Climate 02_08_2016.csv");
var fileContents = ReadFile(fileName);
string[] fileLines = fileContents.Split(new char[] { 'r', 'n' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var line in fileLines)
{
Console.WriteLine(line);
}
}
public static string ReadFile(string fileName)
{
var column5 = new List<string>();
using (var reader = new StreamReader(fileName))
{
while (reader.EndOfStream)
{
var splits = reader.ReadLine().Split(';');
column5.Add(splits[4]);
}
return reader.ReadToEnd();
}
}
}
String.Split splits a string into array of strings based on a delimiter specified. MSDN Reference.
You could use String.Replace method to replace space with a comma.
var result = yourStringVar.Replace(' ', ',')
Here is the full code (slightly simplified).
class Program
{
static void Main(string[] args)
{
var filePath = Path.Combine(Directory.GetCurrentDirectory(), "Climate 02_08_2016.csv");
var fileContents = ReadFile(filePath);
foreach (var line in fileContents)
{
Console.WriteLine(line);
}
Console.WriteLine("Press any key to exit...");
Console.ReadKey();
}
public static IList<string> ReadFile(string fileName)
{
var results = new List<string>();
var lines = File.ReadAllLines(fileName);
for (var i = 0; i < lines.Length; i++)
{
// Skip the line with column names
if (i == 0)
{
continue;
}
// Replace space with a comma
var replace = lines[i].Replace(' ', ',');
results.Add(replace);
}
return results;
}
}
I get following output:
TUI,01/01/20
Press any key to exit...
Please let me know if this is enough for you to implement your own solution.
I wrote a text file. The first item of each line from this text file supposed to be key and rest of the items are values. My text file looks like this-
Flensburg;Nordertor;Naval Academy Mürwik;Flensburg Firth
Kiel;Laboe Naval Memorial;Zoological Museum of Kiel University;Kieler Förde
Lübeck;Holstentor;St. Mary's Church, Lübeck;Passat (ship);Burgtor;Lübeck Museum of Theatre Puppets;Trave
For my project purpose, I need to create .json data for each values and store those vales into the key name folder.As I am very new handling this situation I am not getting the correct logic to do this. However I tried in the follwing way by which I can create the key name folder and and only one subfolder into it. But I need to create all values folder inside the key folder. How can I do it.
My POI class from which I read the text file as key value is-
public class POI
{
Dictionary<string, List<string>> poi = new Dictionary<string, List<string>>();
public bool ContainsKey(string key) { return this.poi.ContainsKey(key); }
public List<string> GetValue(string key) { return this.poi[key]; }
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
poi.Add(parts[0], new List<string>());
poi[parts[0]] = new List<string>(parts.Skip(1));
}
}
}
in the form1.cs
private void button1_Click(object sender, EventArgs e)
{
JSON_Output Json = new JSON_Output();
Json.ToJsonForLocation(comboBox1.Text);
}
also I set selectedindexchange from combobox2
private void comboBox1_SelectedIndexChanged(object sender, EventArgs e)
{
if (comboBox1.SelectedItem != null)
{
POI poi1 = new POI();
poi1.POIList();
string txt = comboBox1.SelectedItem.ToString();
if (poi1.ContainsKey(txt))
{
List<string> points = poi1.GetValue(txt);
comboBox2.Items.Clear();
comboBox2.Items.AddRange(points.ToArray());
}
}
}
now where the json file generated to sore the value is-
public void ToJsonForLocation(string name)
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "Text_ImageWithHash");
string SubfolderName = Path.Combine(folderName, name);
//string folderName = Path.Combine(startPath, "Text_ImageWithHash");
System.IO.Directory.CreateDirectory(SubfolderName);
string fileName = name + ".json";
var path = Path.Combine(SubfolderName, fileName);
var Jpeg_File = new DirectoryInfo(startPath + #"\Image\" + name).GetFiles("*.jpg");
POIData Poi=new POIData();
Poi.Shorttext = File.ReadAllText(startPath + #"\Short Text\" + name + ".txt");
Poi.GeoCoordinates=GeosFromString(startPath + #"\Latitude Longitude\" + name + ".txt");
Poi.Images=new List<string> { Jpeg_File[0].Name};
string json = JsonConvert.SerializeObject(Poi,Formatting.Indented);
File.WriteAllText(path , json);
}
This is my code output while running the program.
after clicking button 1 Text_image_withHash folder is generated in the configuration directory.
Now if I open the folder I can see fthe following folders which is the key value from text file
After enable button 2 for combobox two the values folder is generated but not in the key folder.but as usual way in the Text_Image_withHash.
But What I want to do is-
To create that kind of folder-structure, simply use a foreach-loop. And String.Split.
Required usings:
using System;
using System.IO;
using System.Text;
using System.Linq;
Example:
// basePath can be anything
var basePath = "C:\Something";
// assume "info" is your CSV.
var infoParts = info.Split(new[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (infoParts.Length == 0)
{
return;
}
var rootPath = infoParts[0];
Directory.CreateDirectory(Path.Combine(basePath, rootPath));
foreach (var subPath in infoParts.Skip(1))
{
Directory.CreateDirectory(Path.Combine(basePath, rootPath, subPath));
}
Saving JSON-files into these directories could then simply be made by combining the paths in a similar fashion.
I would also suggest some sanitizing of your paths (such as replacing '/' and '\\' with '_' or '-'.
Example implementation:
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new[] { ';' },
StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
{
// Empty line or similar.
continue;
}
string cityName = parts[0];
poi.Add(cityName, new List<string>());
// Add the points of interest to local.
var points = new List<string>(parts.Skip(1));
poi[cityName] = points;
// basePath will have to be retrieved somehow. It's up to you.
string cityDirectoryPath = Path.Combine(basePath, cityName));
// Create a directory for the city.
Directory.CreateDirectory(cityDirectoryPath);
// Create sub-directories for points.
foreach (string point in points)
{
Directory.CreateDirectory(Path.Combine(
cityDirectoryPath, point));
}
}
}
I have just got my answer. This is the solution of the above question.
For POI Class :
public class POI
{
Dictionary<string, List<string>> poi = new Dictionary<string, List<string>>();
public bool ContainsKey(string key) { return this.poi.ContainsKey(key); }
public List<string> GetValue(string key) { return this.poi[key]; }
public void POIList()
{
foreach (string line in File.ReadLines("POIList.txt"))
{
string[] parts = line.Split(new char[] { ';' }, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 0)
{
// Empty line or similar.
continue;
}
string cityName = parts[0];
poi.Add(cityName, new List<string>());
// Add the points of interest to local.
var points = new List<string>(parts.Skip(1));
poi[cityName] = points;
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "FinalJson");
string cityDirectoryPath = Path.Combine(folderName, cityName);
Directory.CreateDirectory(cityDirectoryPath);
}
}
}
the the json output class
public void ToJsonForLocation(string CityName,string PoiName)
{
var startPath = Application.StartupPath;
string folderName = Path.Combine(startPath, "FinalJson");
string SubfolderName = Path.Combine(folderName, CityName);
System.IO.Directory.CreateDirectory(SubfolderName);
string fileName = PoiName + ".json";
var path = Path.Combine(SubfolderName, fileName);
var Jpeg_File = new DirectoryInfo(startPath + #"\Image\" + PoiName).GetFiles("*.jpg");
POIData Poi=new POIData();
Poi.Shorttext = File.ReadAllText(startPath + #"\Short Text\" + PoiName + ".txt");
Poi.GeoCoordinates = GeosFromString(startPath + #"\Latitude Longitude\" + PoiName + ".txt");
Poi.Images=new List<string> { Jpeg_File[0].Name};
string json = JsonConvert.SerializeObject(Poi,Formatting.Indented);
File.WriteAllText(path,json);
}
this is generated folder and file in this way-
The Final json file for all values
So, I know my headline is a bit confusing, I will explain.
My code looks like this:
string filename = "C:\\C#\\maplist.txt"; // please put the text file path.
string filename2 = "C:\\C#\\zemaplist.txt";
string map;
StreamReader sr = new StreamReader(filename);
StreamWriter sw = new StreamWriter(filename2);
List<string> maps = new List<string> { };
while ((map = sr.ReadLine()) != null)
{
maps.Add(map);
}
sr.Close();
for (int i = 0; i < maps.Count; i++)
{
Console.WriteLine(maps[i]);
sw.WriteLine(maps[i]);
}
sw.Close();
and what i need to do is when the code read a new line, in my line there is
"Hey,Hey"
I want to split the , from each other so I can take both of them as other parameters, so that the first Hey will be added to maps and the other hey will be maps2,
How can I do that?
You can use Split() function to Split the given String based on delimiter.
Try This:
while ((map = sr.ReadLine()) != null)
{
maps.Add(map.Split(',')[0].Trim());
maps2.Add(map.Split(',')[1].Trim());
}
Simple Code:
using System.IO;
string filename = "C:\\C#\\maplist.txt"; // please put the text file path.
string filename2 = "C:\\C#\\zemaplist.txt";
string map;
StreamWriter sw = new StreamWriter(filename2);
List<string> maps = new List<string> { };
List<string> maps2 = new List<string> { };
String [] allLines = File.ReadAllLines(filename);
foreach(String line in allLines)
{
maps.Add(line.Split(',')[0].Trim());
maps2.Add(line.Split(',')[1].Trim());
}
for (int i = 0; i < maps.Count; i++)
{
Console.WriteLine(maps[i]);
sw.WriteLine(maps[i]);
}
sw.Close();
Solution 2:
String mapItem1="";
String mapItem2="";
if(maps.Count == maps2.Count)
{
for(int i=0;i<maps.Count;i++)
{
mapItem1=maps[i];
mapItem2=maps2[i];
}
}
while ((map = sr.ReadLine()) != null)
{
string[] split = map.Split(',');
//First Hey would be split[0], second Hey would be split[1]
maps.Add(split[0].Trim());
maps2.Add(split[1].Trim());
}
The Split method should help you out with that.
If you want to trim leading whitespace characters, you can use the .Trim() method on a string.
Use Split().
string heys = "Hey,Hey";
string[] splitArray = heys.Split(',');
Then you have:
splitArray[0] = "Hey";
splitArray[1] = "Hey";
Why even bother reading line by line? Read the entire file, replace the new line chars for a "," (to prevent last and first elements from different lines to be treated as one), and loop through a clean string.
string fileContent = Regex.Replace(File.ReadAllText("test.txt"), #"\r", ",");
List<string> mapList = new List<string>();
foreach (string map in Regex.Split(fileContent.Replace(#"\s+", ""), ","))
{
mapList.Add(map.Trim());
}
The output of my app is producing duplicates of filenames...and i'm not 100% sure why that is.
My app "cleans" the file name by finding the regex pattern in the filename. If there is none, it dumps it into a "normal" list and ignores it.
Here is the code i'm using to display my output: [this keeps showing me duplicates of filenames!!]
public partial class DriveRecursion_Results : Form
{
List<string> paths = new List<string>();
public DriveRecursion_Results()
{
InitializeComponent();
}
public void DriveRecursion(string retPath)
{
string pattern = (#"[~#&!%+{}]+");
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
List<string> normal = new List<string>();
List<string> fileNameOnlyList = new List<string>();
dataGridView1.Rows.Clear();
try
{
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
foreach (string nameOnly in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
{
//string fileNameOnly = Path.GetFileName(fileNames);
string pathOnly = Path.GetDirectoryName(fileNames);
DataGridViewRow dgr = new DataGridViewRow();
dgr.CreateCells(dataGridView1);
dgr.Cells[0].Value = pathOnly;
dgr.Cells[1].Value = nameOnly;
dataGridView1.Rows.Add(dgr);
string pathforInvalidName = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(nameOnly), pathOnly);
paths.Add(pathforInvalidName);
}
else
{
normal.Add(strippedFileName);
}
}
}
}
catch (Exception e)
{
StreamWriter sw = new StreamWriter(retPath + "ErrorLog.txt");
sw.Write(e);
}
}
private void button1_Click_1(object sender, EventArgs e)
{
this.Close();
CleanNames clean = new CleanNames();
clean.Sanitizer(paths);
clean.Show();
}
Once it's done identifying which files need to be renamed, it cleans up the "dirty" names:
public partial class CleanNames : Form
{
public CleanNames()
{
InitializeComponent();
}
public void Sanitizer(List<string> paths)
{
string regPattern = (#"[~#&!%+{}]+");
string replacement = " ";
Regex regExPattern = new Regex(regPattern);
Regex regExPattern2 = new Regex(#"\s{2,}");
StreamWriter errors = new StreamWriter(#"S:\Test\Errors.txt", true);
var filesCount = new Dictionary<string, int>();
dataGridView1.Rows.Clear();
try
{
foreach (string files2 in paths)
{
string filenameOnly = System.IO.Path.GetFileName(files2);
string pathOnly = System.IO.Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
sanitizedFileName = regExPattern2.Replace(sanitizedFileName, replacement);
string sanitized = System.IO.Path.Combine(pathOnly, sanitizedFileName);
if (!System.IO.File.Exists(sanitizedFileName))
{
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = sanitizedFileName;
dataGridView1.Rows.Add(clean);
System.IO.File.Move(files2, sanitized);
}
else
{
if (filesCount.ContainsKey(sanitizedFileName))
{
filesCount[sanitized]++;
}
else
{
filesCount.Add(sanitized, 1);
}
string newFileName = String.Format("{0}{1}{2}",
System.IO.Path.GetFileNameWithoutExtension(sanitized),
filesCount[sanitized].ToString(),
System.IO.Path.GetExtension(sanitized));
string newFilePath = System.IO.Path.Combine(System.IO.Path.GetDirectoryName(sanitized), newFileName);
newFileName = regExPattern2.Replace(newFileName, replacement);
System.IO.File.Move(files2, newFilePath);
sanitized = newFileName;
DataGridViewRow clean = new DataGridViewRow();
clean.CreateCells(dataGridView1);
clean.Cells[0].Value = pathOnly;
clean.Cells[1].Value = filenameOnly;
clean.Cells[2].Value = newFileName;
dataGridView1.Rows.Add(clean);
}
}
}
catch (Exception e)
{
errors.Write(e);
}
}
private void SanitizeFileNames_Load(object sender, EventArgs e)
{ }
private void dataGridView1_CellContentClick(object sender, DataGridViewCellEventArgs e)
{
}
private void button1_Click(object sender, EventArgs e)
{
Application.Exit();
}
What i'm trying to do here is ONLY show files that need to be renamed (not all files). I want to take those dirty filenames and clean them with my 2nd class.
Anybody know why i'm seeing multiples of the same file on the output? Anybody know how to fix this?!?!
My immediate observation is that your foreach (string nameOnly in fileNameOnlyList) loop should not be nested where it is. Your logic looks like this.
For each filename:
Add it to the list.
For *everything in the list*...
So you'll add one. Then process it. Then add another. Then process both. Then add. Then process all three. Etcetera.
Try this.
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
}
foreach (string strippedFileName in fileNameOnlyList)
{
if (regEx.IsMatch(strippedFileName))
// ...
}
Edit
Even better, why have two loops?
foreach (string fileNames in fileDrive)
{
string strippedFileName = System.IO.Path.GetFileName(fileNames);
fileNameOnlyList.Add(strippedFileName);
if (regEx.IsMatch(strippedFileName))
// ...
}
My first guess is that you are seeing duplicates because you have the loop over fileNameOnlyList inside the loop over fileDrive. This when you are processing second file name from fileDrive collection, you will add the first one to your data grid as well.
There are two possible ways to fix it:
- move the inner loop out of the outer loop and put it just under it
- remove the inner loop (but leave the code that is inside it) and use strippedFileName instead of nameOnly variable in the code
You search recursively through your directory structure
Directory.GetFiles(retPath, "*.*", SearchOption.AllDirectories);
but you use only the filename
System.IO.Path.GetFileName(fileNames);
So if you have the same file in nested folders, it will show up twice.