Having Trouble Renaming Files that Match with my RegEx - c#

I have an app that "cleans" "dirty" filenames. "Dirty" filenames have #%&~+{} in their filenames. What my app does is see if they are a match for a RegEx pattern i have defined and then send it to a method called FileCleanUp where it "cleans" the file and replaces invalid chars with a "". However, i noticed while i was running this, that my FileCleanup method only works on SOME files and not others!
Here is my code:
public class SanitizeFileNames
{
public void FileCleanup(List<string>paths)
{
string regPattern = (#"[~#&!%+{}]+");
string replacement = "";
Regex regExPattern = new Regex(regPattern);
foreach (string files2 in paths)
try
{
string filenameOnly = Path.GetFileName(files2);
string pathOnly = Path.GetDirectoryName(files2);
string sanitizedFileName = regExPattern.Replace(filenameOnly, replacement);
string sanitized = Path.Combine(pathOnly, sanitizedFileName);
//write to streamwriter
System.IO.File.Move(files2, sanitized);
}
catch (Exception e)
{
//write to streamwriter
}
}
I tested on a few files with the names like: ~Test.txt, #Test.txt, +Text.txt, Test&Test.txt, T{e}st.txt, Test%.txt.
The ones i could not get to be renamed were: ~Test.txt, +Test.txt, T{e}st.txt
I debugged this and weirdly enough, it shows that these files that did not get renamed for some reason as correct on the debugger. Instead of showing ~Test.txt as a "sanitized" file name, it was Text.txt. So on the app side, it DOES read my foreach loop correctly.
However, i'm really stumped as to why it's not actually renaming these files. Anybody have a clue as to why this might be? Does it have to do with the File.Move() ?
EDIT: On further testing, i realize that it also doesn't rename files that are like this: ~~test.txt or ##test.txt

You have an empty catch block. Why don't you print out the exception message to see what's happening?
My guess is that the file names are matching the regex, but you're unable to rename the files because a file named Test.txt already exists after #Test.txt is renamed to that. Try renaming the other files to ~Test2.txt, +Test3.txt, T{e}st4.txt before running the program again.

Related

How to move a file that has no file extension? C#

if (File.Exists(#"C:\\Users" + Environment.UserName + "\\Desktop\\test"))
{ /\
this file has no file extension
}
The file test has no extension and I need help to either move or rename this file to something with a extension
Having no extension has no bearing on the function.
Also, a rename is really just a move "in disguise", so what you want to do is
File.Move(#"C:\Users\Username\Desktop\test", #"C:\Users\Username\Desktop\potato.txt")
Please bear in mind the # before the string, as you haven't escaped the backslashes.
There's nothing special about extensionless files. Your code is broken because you use string concatenation to build a path and you're mixing verbatim and regular string literal syntax. Use the proper framework method for this: Path.Combine().
string fullPath = Path.Combine(#"C:\Users", Environment.UserName, #"Desktop\test");
if(File.Exists(fullPath))
{
}
You also should use the proper framework method to get the desktop path for the current user, see How to get a path to the desktop for current user in C#?:
string desktopPath = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
string fullPath = Path.Combine(desktopPath, "test");
Then you can call File.Move() to rename the file, see Rename a file in C#:
if(File.Exists(fullPath))
{
string newPath = fullPath + ".txt";
File.Move(fullPath, newPath);
}
You can get all files without extension in this way:
var files = Directory.EnumerateFiles(#"C:\Users\Username\Desktop\")
.Where(fn => string.IsNullOrEmpty(Path.GetExtension(fn)));
Now you can loop them and change the extension:
foreach (string filePath in filPaths)
{
string fileWithNewExtension = Path.ChangeExtension(filePath, ".txt");
string newPath = Path.Combine(Path.GetDirectoryName(filePath), fileWithNewExtension);
File.Move(filePath, newPath);
}
As you can see, the Path-class is a great help.
Update: if you just want to change the extension of a single file that you already know it seems that Dasanko has already given the answer.

C# mass File renamer

i want to create C# mass file renamer, here is my UI
i have created tes folder, inside of tes there's a file which is 1.txt.
i want to create my program to add prefix and suffix to the files, so 1.txt will become
prefix1suffix
but then i got an error
it's said file already exist though there's only one file on tes folder, which is 1.txt how do i make it work ? where's the error comes from ?
i have tried the following code
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
File.Move(f.FullName,"stackoverflow");
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
and it returns same error as the second picture above.
the following picture is tes folder, there's nothing in tes folder except 1.txt
You are calling File.Move() with a full path for your sourceFileName and a relative path for your destFileName. The relative file path is relative to the current working directory and not to the source file path. I expect that a stackoverflow file exists in the current working directory, most likely created the first time you ran this code.
your File.Move is changing them all to StackOverflow not using the prefix and suffix. If you only have one file in the directory it shouldn't be an issue. Are you sure there is only 1 file?
public static void Move(
string sourceFileName,
string destFileName
)
Looking at this answer might be the clue as you are specifying relative path for the destination file. To obtain the current working directory, see GetCurrentDirectory
The sourceFileName and destFileName arguments are permitted to specify
relative or absolute path information. Relative path information is
interpreted as relative to the current working directory.
You should change
File.Move(f.FullName,"stackoverflow");
to
string fileName = f.Name.Replace(f.Extenstion,string.Empty);
string newFileName = string.Format("{0}{1}{2}",prefix,fileName,suffix);
string newFileWithPath = Path.Combine(f.Directory,newFileName);
if (!File.Exists(newFileWithPath))
{
File.Move(f.FullName,newFileWithPath);
}
The code above will give you that error since, after the first run through, "stackoverflow" exists as a file. Make sure that you check if the destination file exists (using File.Exists) before calling File.Move.
Since your goal is renaming, I would suggest using a test folder filled with files rather than using a piecemeal approach. See if something like this helps:
private void Rename(string prefix, string filepath, string suffix)
{
//i don't use prefix suffix yet to make sure if my function works
DirectoryInfo d = new DirectoryInfo(filepath);
FileInfo[] file = d.GetFiles();
try
{
foreach (FileInfo f in file )
{
f.MoveTo(#filepath + #"\" + prefix + f.Name.Insert(f.Name.LastIndexOf('.'),suffix));
}
}
catch (Exception e)
{
cmd.cetakGagal(e.ToString(), title);
}
cmd.cetakSukses("Rename Success", title);
}
on a side note using a listview to display the filenames and the changes before they're committed will help prevent unwanted changes.

Outputting all text file titles to a textbox on Windows Form

Getting a bit stuck on a piece of code I'm trying to write and was hoping for a helping hand if anyone knows where I'm going wrong!
I have a simple Windows Form where I have a folder browser. The user will browse to a folder and any sub-folders within will then be searched for a text file that has the word "Passed" in the title (not the body of the text file itself). There will be files with "Passed" in from many different folders, and I want the functionality of the app to search through all sub-folders and return the all the files that have this in their name.
At present I have the following code:
private void searchButton_Click(object sender, EventArgs e)
{
if (textBox1.Text == "")
{
MessageBox.Show("Please enter a path");
}
else
{
string[] allFiles = Directory.GetFiles(textBox1.Text, "*Passed*.*", SearchOption.AllDirectories);
string name = resultsText.Text;
foreach(string file in allFiles)
{
if (file.Contains("Passed"))
{
resultsText.Text = file;
}
}
}
}
However, in the resultsText texbox, it only returns 1 value. There are multiple files with "Passed" in their title and I would like to print them all to this textbox. Does anyone know where I may be going wrong and why I am only getting one file rather than all of them?
Also, this method seems to return the whole file path e.g.)
C:\Program Files\Test\abc\PassedTests.txt - does anyone know how I can trim the full path so it just returns the file name and extension?
Any help is greatly appreciated!
You need to append the text. At the moment, you're overwriting the previous value by using resultsText.Text = file;.
if (file.Contains("Passed"))
{
resultsText.AppendText(file);
}
What may be more performant would to use build your string using a StringBuilder and then assign that to the TextBox.
StringBuilder sb = new StringBuilder();
foreach(string file in allFiles)
{
if (file.Contains("Passed"))
{
sb.Append(file);
}
}
resultsText.Text = sb.ToString();
You have to change 1 line of code:
resultsText.Text = file;
To this:
resultsText.Text += file;
The + will append the text and not overwrite it.
this is the answer for your second question.
try this to get only the file name
Path.GetFileName(filepath)

write the list of files in a folder to afile

I wrote a code to read all the files in a folder, then write them to a file. All the code complies and runs okay, but the filenames of the files are not displayed in the new file.
Code:
private void Form1_Load(object sender, EventArgs e)
{
DialogResult result = folderBrowserDialog1.ShowDialog(); // Show the dialog.
// create a list to insert the data into
//put all the files in the root directory into array
string[] array1 = Directory.GetFiles(#"C:\Users\a3708906\Documents\Filereader m 15062012", "*.csv");
// Display all files.
TextWriter tw1 = new StreamWriter("C:/Users/a3708906/Documents/Filereader m 15062012/Filereader m 15062012/listoffiles.txt");
List<string> filenames = new List<string>();
tw1.WriteLine("--- Files: ---");
foreach (string name in array1)
{
tw1.WriteLine(name);
}
tw1.Close();
}
I would be grateful for your assistance.
You took the trouble to ask the user the folder location, yet you don't retrieve that folder location. The code should be
string[] array1 = Directory.GetFiles(folderBrowserDialog1.SelectedPath, "*.csv");
// Display all files.
TextWriter tw1 = new StreamWriter(folderBrowserDialog1.SelectedPath+"/listoffiles.txt");
If the file isn't created (ie its just not there, even if it's just blank) then you problem lies with the stream writer. If this is the case I would suggest changing the direction of slashes so that your path is
TextWriter tw1 = new StreamWriter("C:\\Users\\a370890\\Documents\\Filereader m 15062012\\Filereader m 15062012\\listoffiles.txt");
If the file is created but nothing is written have a look at the flush command.
tw1.Flush();
Set a breakpoint to verify that GetFiles is returning files.
(Consider renaming array1 to something more meaningful)
Set a breakpoint on tw1.WriteLine(name) and ensure it is being hit.
It should be pretty easy to see the problem. My guess is that you simply aren't getting any files returned from GetFiles, but the breakpoints will tell you for sure. If your output file is created but missing the files - this is most likely the case.
If your output file doesn't exist; take a closer look at your file writing code.
I would say that your "space" in your folderpath is messing things up. Try to escape the "whitespace" by following the explanations in the msdn
I think problem is with your file path or file writing capability.
You use folderbrowserdialog but do not use it to get selected file
name. Instead you give path manually. also your output path can have
problem.
Try this :
using(system.IO.StreamWriter tw1 =
new system.IO.StreamWriter(#"C:/Users/a3708906/Documents/Filereader m 15062012/Filereader m 15062012/listoffiles.txt")
{
foreach (string name in array1)
{
tw1.WriteLine(name);
}
}

Why isn't my File.Move() working?

I'm not sure what exactly i'm doing wrong here...but i noticed that my File.Move() isn't renaming any files.
Also, does anybody know how in my 2nd loop, i'd be able to populate my .txt file with a list of the path AND sanitized file name?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Text.RegularExpressions;
namespace ConsoleApplication2
{
class Program
{
static void Main(string[] args)
{
//recurse through files. Let user press 'ok' to move onto next step
string[] files = Directory.GetFiles(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing", "*.*", SearchOption.AllDirectories);
foreach (string file in files)
{
Console.Write(file + "\r\n");
}
Console.WriteLine("Press any key to continue...");
Console.ReadKey(true);
//End section
//Regex -- find invalid chars
string pattern = " *[\\~#%&*{}/<>?|\"-]+ *";
string replacement = " ";
Regex regEx = new Regex(pattern);
string[] fileDrive = Directory.GetFiles(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing", "*.*", SearchOption.AllDirectories);
List<string> filePath = new List<string>();
//clean out file -- remove the path name so file name only shows
string result;
foreach(string fileNames in fileDrive)
{
result = Path.GetFileName(fileNames);
filePath.Add(result);
}
StreamWriter sw = new StreamWriter(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing\File_Renames.txt");
//Sanitize and remove invalid chars
foreach(string Files2 in filePath)
{
try
{
string sanitized = regEx.Replace(Files2, replacement);
sw.Write(sanitized + "\r\n");
System.IO.File.Move(Files2, sanitized);
System.IO.File.Delete(Files2);
}
catch (Exception ex)
{
Console.Write(ex);
}
}
sw.Close();
}
}
}
I'm VERY new to C# and trying to write an app that recurses through a specific drive, finds invalid characters (as specified in the RegEx pattern), removes them from the filename and then write a .txt file that has the path name and the corrected filename.
Any ideas?
Your filepath list contains only the file names. You have removed the directory info from them in the call to Path.GetFileName(), so your File.Move is looking for the target file in the application's default directory, rather than its original location.
I think your code for saving the sanitized file names is correct though. You should use the using() construct around your StreamWriter though, as below, to ensure that the file is closed once you're done with it.
//clean out file -- remove the path name so file name only shows
string result;
foreach(string fileNames in fileDrive)
{
// result = Path.GetFileName(fileNames); // don't do this.
filePath.Add(fileNames);
}
using (StreamWriter sw = new StreamWriter(#"C:\Documents and Settings\jane.doe\Desktop\~Test Folder for [SharePoint] %testing\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);
}
catch
{
}
}
}
Are any exceptions being thrown in the call to File.Move()? You have an empty catch block beneath it which will be stopping you from seeing them. Try removing the catch{} or putting some code in there to log any exceptions.
Try using File.AppendAllLines() (with a collection) or File.AppendAllText() (for each individually) instead of a stream. That will make things a little easier.
Also, I understand not wanting your application to bomb, but at the very least, while you're currently writing/debugging comment your try block out so that you can see the exceptions.
Probably not an answer, but perhaps a suggestion to help.

Categories

Resources