Check if file exists in folder in c# - c#

I am moving files from source folder to destination folder. Before moving files, I am checking that directory exists or not which is working fine. The issue is with my second check where I want to make sure that folder is not empty before moving files but it is not giving me correct result.
public void MoveFilesFromTempToSourceTbl()
{
//Moving all files from temp folder to orig folder.
string sourceFolder = (twitterDO.Path + "\\" + msgDate.Year.ToString() + "\\" + msgDate.Month.ToString() + "\\" + msgDate.Day.ToString() + "_Temp").Replace("\\", #"\");
string destinationFolder = (twitterDO.Path + "\\" + msgDate.Year.ToString() + "\\" + msgDate.Month.ToString() + "\\" + msgDate.Day.ToString()).Replace("\\", #"\");
string pattern = "*.txt";
if (Directory.Exists(sourceFolder))
{
if (File.Exists(pattern))
{
foreach (var file in new DirectoryInfo(sourceFolder).GetFiles(pattern))
{
file.MoveTo(Path.Combine(destinationFolder, file.Name));
}
}
if (Directory.GetFiles(sourceFolder).Length == 0) //Before deleting make sure that Temp folder is empty.
Directory.Delete(sourceFolder, true); // Delete Temp folder after moving all the contents.
}
}
I know I am making some small mistake but not sure what it is. Following is the screenshot of the result which I got in immediate window.
http://imgur.com/FZvo9cj

There's a bit of redundancy in your current code. Starting with the if-checks, here's how I would approach this:
var sourceDirectory = new DirectoryInfo(sourceFolder); // remember this, it is reused
if (sourceDirectory.Exists)
{
// Look for the files in the directory, if none found, will be empty array
foreach (var file in sourceDirectory.GetFiles(pattern))
{
file.MoveTo(Path.Combine(destinationFolder, file.Name));
}
// Re-check the directory for any remaining files
if (sourceDirectory.GetFiles(pattern).Length == 0) //Before deleting make sure that Temp folder is empty.
sourceDirectory.Delete(); // Delete Temp folder after moving all the contents.
}
As a small performance improvement, you could replace sourceDirectory.GetFiles() with sourceDirectory.EnumerateFiles() in the for-loop. This will allow you to start moving them as the method finds them, not after they have all been found.

You are passing "*.txt" into the File.Exists() call when you need to be passing a path.
You can read the Documentation here
Alternatively you could use something like this:
Directory.GetFiles(destinationFolder).Contains(filename)

I agree with David here but also I think the flow of you logic should be adjusted a bit. The File.Exixts(filename); should occur inside the foreach.
That will allow you to iterate each file and if it exists do something.

Try adding the following to check if any files exist in the location:
bool exist = Directory.EnumerateFiles(sourceFolder, "*.txt").Any();

Related

Check if filename exist in the folder directory

Hi I have a code that you can save file and give specific file naming.
the problem is how can I check if file exist in the folder directory.
What I'm trying to do is like this.
FileInfo fileInfo = new FileInfo(oldPath);
if (fileInfo.Exists)
{
if (!Directory.Exists(newPath))
{
Directory.CreateDirectory(newPath);
}
fileInfo.MoveTo(string.Format("{0}{1}{2}", newPath, extBox1t.Text + "_" + textBox2.Text + "_" + textBox3.Text, fileInfo.Extension));
im trying to add MessageBox.Show in the below
if (!Directory.Exists(newPath))
{
MessageBox.Show("File Exist. Please Rename!");
Directory.CreateDirectory(newPath);
But it does not work. Or is there a way to add extension name at the last part of filename it should like this
Example: STACKOVERFLOWDOTCOME_IDNUM_11162022_0
if STACKOVERFLOWDOTCOME_IDNUM_11162022 exist it will rename to STACKOVERFLOWDOTCOME_IDNUM_11162022_0
it will add _0 at the last part.
One way to do it is to write a method that extracts the directory path, name, and extension of the file from a string that represents the full file path. Then we can create another variable to act as the "counter", which we'll use to add the number at the end of the file name (before the extension). We can then create a loop that checks if the file exists, and if it doesn't we'll increment the counter, insert it into the name, and try again.
For example:
public static string GetUniqueFileName(string fileFullName)
{
var path = Path.GetDirectoryName(fileFullName);
var name = Path.GetFileNameWithoutExtension(fileFullName);
var ext = Path.GetExtension(fileFullName);
var counter = 0;
// Keep appending a new number to the end of the file name until it's unique
while(File.Exists(fileFullName))
{
// Since the file name exists, insert an underscore and number
// just before the file extension for the next iteration
fileFullName = Path.Combine(path, $"{name}_{counter++}{ext}");
}
return fileFullName;
}
To test it out, I created a file at c:\temp\temp.txt. After running the program with this file path, it came up with a new file name: c:\temp\temp_0.txt

Error while trying to rename files using C#

I have the following code to rename files in the following tree as from 00000001.pdf to the last file with this 8 character left padding, e.g: 00000100.pdf
Folder1
subfolder1
childfolder1
pdffile1
pdffile2
childfolder2
pdffile3
pdffile4
subfolder2
childfolder3
pdffile5
pdffile6
But for some reason in some of those child folders it keeps renaming them with no end.
Some times it just jumps to another number, as if it was an async operation. But if I stop and start again it goes okay until the second next folder, when it messes up again.
But this error only happened within 19 folders.
Indeed their pdf names are different from the others, but I don't see how it is related.
The other files were named something like "DOCUMENT_01" and so on, but these are:
0000000100000001.pdf
0000000200000001.pdf
0000000300000001.pdf
etc
static void Main(string[] args)
{
Console.WriteLine("Digite a pasta 'pai' onde serão buscados pdfs dentro das pastas 'filhas':");
string path = Console.ReadLine();
foreach (string dir in Directory.EnumerateDirectories(path))
{
foreach (string subdir in Directory.EnumerateDirectories(dir))
{
Console.WriteLine($"{dir} - {subdir}");
int n = 1;
foreach (string pdffile in Directory.EnumerateFiles(subdir, "*.pdf", SearchOption.AllDirectories))
{
Console.WriteLine(n.ToString().PadLeft(8, '0') + " " + new FileInfo(pdffile).Length);
File.Move(pdffile, subdir + $"\\{n.ToString().PadLeft(8, '0')}.pdf");
n++;
}
Console.WriteLine("\n\n");
}
}
}
What could be going wrong?
It should await for the File.Move method to end to add the n + 1 and then moving to the next pdffile as a synchronous operation. So why does it jumps numbers after a random time and why it keeps going forever other times?
And just to remember, if I stop the program and start again and put the folder that was messed up as the first one, it goes ok and only when it goes to the next folder, or the folder after next that it start to give me this error again.
Hope that I could make myself clear... Thanks for your attention!
EDIT: will try using FileInfo class to give me the parent folder with the SearchOption.AllDirectories option and exclude this 3 stage loop plus actually working for any kind of tree structure
EDIT2: Tried, worked as a "tree indepent" script but getting the same result with the files name after the first folder... As it's really fast, in 3 seconds it goes from 00000169.pdf to 00006239.pdf in a folder with just 330 items.
As commented already, it is not a good idea to move or rename files “WHILE” the code is enumerating though the list of those files as the posted code appears to do. This will cause obvious problems and you should simply mark the files somehow, then later come back and rename or move them.
More importantly, the big issue related to renaming/moving files is exactly as you describe with your current issue. The problem is that the errors are erratic and not consistent. Making it very difficult to trace. However, the problems you describe are classic trademarks of moving/renaming files while enumerating through those files.
With that said, the best way and easiest way to traverse an unknown number of folder levels given a starting folder is by using recursion. In a lot of cases, recursion can be avoided with some well though out loops, however when we do not know how many levels of folders there are, then, using a simple loop or foreach loop paradigm may be doable, however, you will most likely be adding variables and code that only makes this more complex. This is shown in the current code with the addition of the dir variable to keep track of “when” a different folder is used. Recursion is suited ideally for this situation.
In this case, this recursive method will be called ONCE for each folder and subfolders from a given “starting” folder location. This means that each time this recursive method is called is when a different folder is beginning to be processed. So n would always start at 1 and we do not need to keep track of the current folders path.
So the signature of this method will take a DirectoryFolder object as a “starting” folder. First we create some variables; a FileInfo array pdffiles to hold the pdf files in the given folder; in addition to a DirectoryInfo array foldersInThisFolder to hold all the other folders in this starting folder. Lastly an int n to index the files as the posted code is doing.
Next we get all the pdf files in this “starting” folder. If there are pdf files in this folder, then we loop through those files and process them. Next, we get all the other folders in this “starting” folder. Then start a loop through each folder. For each folder in this collection we will make the recursive call back to this method using the next folder as the “starting” folder, then the whole process continues until the loop through those folders ends.
static void TraverseDirectoryTree(DirectoryInfo startingFolder) {
FileInfo[] pdffiles = null;
DirectoryInfo[] foldersInThisFolder = null;
int n = 1;
Console.WriteLine(startingFolder.FullName);
// get all the pdf files in this folder
try {
pdffiles = startingFolder.GetFiles("*.pdf");
}
catch (Exception e) {
// you may want to catch specific exceptions
// however in this example we do not care what
// the exception is, we will simply ignore this.
// in most cases pdffiles will be null if an exception is thrown
Console.WriteLine(e.Message);
}
if (pdffiles != null) {
foreach (FileInfo pdffile in pdffiles) {
Console.WriteLine(pdffile.FullName + " -> " + n.ToString().PadLeft(8, '0') + " " + pdffile.Length);
//File.Move(pdffile.FullName, pdffile.DirectoryName + $"\\{n.ToString().PadLeft(8, '0')}.pdf");
// add file path to a list of files to rename later?
n++;
}
// start over wiith the sub folders in this folder
foldersInThisFolder = startingFolder.GetDirectories();
foreach (DirectoryInfo dirInfo in foldersInThisFolder) {
TraverseDirectoryTree(dirInfo);
}
}
}
Usage…
Console.WriteLine("Type the folder you want to start with:");
string path = Console.ReadLine();
DirectoryInfo di = new DirectoryInfo(path);
TraverseDirectoryTree(di);
Edit… after further testing it appears that what you are wanting to do is simply “rename” the pdf files. As suggested a simple solution is to save the files that we want to rename, then, after we collect the files we want to rename, we simply loop through those files and rename them. This should eliminate any problems by renaming files while enumerating though the files collection.
To help, I created a Dictionary<string, int> called filesToRename. While recursively looping through all the folders, we will add the full path of each pdf file we want to rename as the Key and the int value n as the Value. After the dictionary is filled we would simply loop through it and rename the files.
private static Dictionary<string, int> filesToRename = new Dictionary<string, int>();
Then replace the commented-out line in the recursive method TraverseDirectoryTree…
//File.Move(pdffile.FullName, pdffile.DirectoryName + $"\\{n.ToString().PadLeft(8, '0')}.pdf");
With…
filesToRename.Add(pdffile.FullName, n);
Then after the dictionary is filled we would loop through it and rename the files, something like…
DirectoryInfo di = new DirectoryInfo(path);
TraverseDirectoryTree(di);
foreach (KeyValuePair<string, int> kvp in filesToRename) {
int index = kvp.Key.ToString().LastIndexOf(#"\");
string dir = kvp.Key.ToString().Substring(0, index);
File.Move(kvp.Key, dir + $"\\{kvp.Value.ToString().PadLeft(8, '0')}.pdf");
}
I am hoping this makes sense…
Answer as Klaus Gütter helped me, I just added .ToList() to the Directory.EnumerateFiles so it made a fixed list first, and then made the foreach for each file
It will rename every pdf within the folder and it's subfolders
Console.WriteLine("Type the folder you want to start with:");
string path = Console.ReadLine();
string dir = "";
int n = 1;
foreach (string pdffile in Directory.EnumerateFiles(path, "*.pdf", SearchOption.AllDirectories).ToList())
{
FileInfo fi = new FileInfo(pdffile);
if (fi.DirectoryName == dir)
{
Console.WriteLine("\t" + n.ToString().PadLeft(8, '0'));
File.Move(pdffile, dir + $"\\{n.ToString().PadLeft(8, '0')}.pdf");
n++;
}
else
{
n = 1;
dir = fi.DirectoryName;
Console.WriteLine("\n\n" + dir);
File.Move(pdffile, dir + $"\\{n.ToString().PadLeft(8, '0')}.pdf");
Console.WriteLine("\t" + n.ToString().PadLeft(8, '0'));
n++;
}
}

CreatDirectory or Delete directory is slower than code

Just a quick question if you can help me, please.
In C#, I am creating a directory, if it does not exist. In the next command, I am checking if the directory exists, I will copy some files.
The Problem is, to creating a new directory or Deleting it, takes time and slower than next code execution time.
The software gives an error of "The folder does not exist ".
I used Thread.Sleep(5000); to wait 5 seconds before copying the content to the directory.
It seems to be working but I feel like that this is not how it's supposed to be done. Does anyone know better coding?
string logDirectoryPath = Directory.GetCurrentDirectory() + "\\LogFiles";
if (!Directory.Exists(logDirectoryPath))
{
Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\LogFiles");
Thread.Sleep(5000);
}
if (Directory.Exists(Directory.GetCurrentDirectory() + "\\LogFiles"))
{
var s = logDirectoryPath + "\\Log_" + DateTime.Now.ToString("dd_MM_yyyy") + ".txt";
using (StreamWriter w = File.AppendText(s))
{
w.WriteLine("--");
w.Write("\r\nLog Entry : ");
w.WriteLine($"{DateTime.Now.ToLongTimeString()} {DateTime.Now.ToLongDateString()}");
}
}
//EDIT
JUST thought maybe I should use a loop?
While(!Directory.Exists(logDirectoryPath))
{
Directory.CreateDirectory(Directory.GetCurrentDirectory() + "\\LogFiles");
}
Use DirectoryInfo
DirectoryInfo di = new DirectoryInfo(#{PATHSTRING});
and use di.Exists to check it exists / di.Create() to create folder
and I'd like to recommend to use logDirectoryPath which you defined already.
like this
DirectoryInfo di = new DirectoryInfo(logDirectoryPath);
if ( !di.Exists ) {
di.Create();
}

Trouble specifying destination filename for use in FileInfo.Copy example from MSDN

I'm using two DateTimePickers to specify a date range, then I'm using a CheckedListBox to specify some strings for filenames with wildcards to enumerate in each day's subdirectory contained within a system environment variable path. I want to copy from that source to a destination using FileInfo.Copy.
I have my code already creating the necessary directories. But I'm having trouble specifying the destination filenames -- they are not being specified at all with how I have this written.
I was thinking of using regular expressions, but after some digging I found this MSDN article that seems to do what I want already. I think I need to alter my code in order to use it. I could use some assistance fitting what I already have into what MSDN shows in its example.
I have been on this part of my program for a month now, which has led me to learn quite a bit about c#, parallel programming, async, lambda expressions, background workers, etc. What seems should be simple has become a big rabbit hole for me. For this question I just need a nudge in the right direction, and I will greatly appreciate it!
Here is my code as it stands:
private async void ProcessFiles()
{
// create a list of topics
var topics = topicsBox.CheckedItems.Cast<string>().ToList();
// create a list of source directories based on date range
var directories = new List<string>();
var folders = new List<string>();
for (DateTime date = dateTimePicker1.Value.Date;
date.Date <= dateTimePicker2.Value.Date;
date = date.AddDays(1))
{
directories.Add(_tracePath + #"\" + date.ToString("yyyy-MM-dd") + #"\");
folders.Add(#"\" + date.ToString("yyyy-MM-dd") + #"\");
}
// create a list of source files to copy and destination
// revise based on https://msdn.microsoft.com/en-us/library/kztecsys.aspx?f=255&MSPPError=-2147217396
foreach (var path in directories)
{
var path1 = path;
try
{
foreach (var files2 in folders)
{
// create the target directory
var destPath = textBox1.Text + #"\" + textBox4.Text + files2;
Console.WriteLine("Target directory is {0}", destPath);
Console.WriteLine("Destination filename is {0}", files2);
foreach (var files in topics)
{
foreach (string sourcePath in Directory.EnumerateFiles(path1, files + "*.*", SearchOption.AllDirectories))
{
// copy the files to the temp folder asynchronously
Console.WriteLine("Copy {0} to {1}", sourcePath, destPath);
Directory.CreateDirectory(sourcePath.Replace(sourcePath, destPath));
}
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
So sourcePath contains the source path and filename. You can easily construct the destination path from that, like so:
// Get just the filename of the source file.
var filename = Path.GetFileName(sourcePath);
// Construct a full path to the destination by combining the destination path and the filename.
var fullDestPath = Path.Combine(destPath, filename);
// Ensure the destination directories exist. Don't pass in the filename to CreateDirectory!
Directory.CreateDirectory(destPath);
Then you can copy the file (synchronously) like this:
File.Copy(sourcePath, fullDestPath);

Moving files based on name to the corresponding folder

Hello everyone and well met! I have tried a lot of different methods/programs to try and solve my problem. I'm a novice programmer and have taken a Visual Basic Class and Visual C# class.
I'm working with this in C#
I started off by making a very basic move file program and it worked fine for one file but as I mentioned I will be needing to move a ton of files based on name
What I am trying to do is move .pst (for example dave.pst) files from my exchange server based on username onto a backup server in the users folder (folder = dave) that has the same name as the .pst file
The ideal program would be:
Get files from the folder with the .pst extension
Move files to appropriate folder that has the same name in front of the .pst file extension
Update:
// String pstFileFolder = #"C:\test\";
// var searchPattern = "*.pst";
// var extension = ".pst";
//var serverFolder = #"C:\test3\";
// String filename = System.IO.Path.GetFileNameWithoutExtension(pstFileFolder);
// Searches the directory for *.pst
DirectoryInfo sourceDirectory = new DirectoryInfo(#"C:\test\");
String strTargetDirectory = (#"C:\test3\");
Console.WriteLine(sourceDirectory);
Console.ReadKey(true);>foreach (FileInfo file in sourceDirectory.GetFiles()) {
Console.WriteLine(file);
Console.ReadKey(true);
// Try to create the directory.
System.IO.Directory.CreateDirectory(strTargetDirectory);
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}
This is just a simple copy procedure. I'm completely aware. The
Console.WriteLine(file);
Console.ReadKey(true);
Are for verification purpose right now to make sure I'm getting the proper files and I am. Now I just need to find the folder based on the name of the .pst file(the folder for the users are already created), make a folder(say 0304 for the year), then copy that .pst based on the name.
Thanks a ton for your help guys. #yuck, thanks for the code.
Have a look at the File and Directory classes in the System.IO namespace. You could use the Directory.GetFiles() method to get the names of the files you need to transfer.
Here's a console application to get you started. Note that there isn't any error checking and it makes some assumptions about how the files are named (e.g. that they end with .pst and don't contain that elsewhere in the name):
private static void Main() {
var pstFileFolder = #"C:\TEMP\PST_Files\";
var searchPattern = "*.pst";
var extension = ".pst";
var serverFolder = #"\\SERVER\PST_Backup\";
// Searches the directory for *.pst
foreach (var file in Directory.GetFiles(pstFileFolder, searchPattern)) {
// Exposes file information like Name
var theFileInfo = new FileInfo(file);
// Gets the user name based on file name
// e.g. DaveSmith.pst would become DaveSmith
var userName = theFileInfo.Name.Replace(extension, "");
// Sets up the destination location
// e.g. \\SERVER\PST_Backup\DaveSmith\DaveSmith.pst
var destination = serverFolder + userName + #"\" + theFileInfo.Name;
File.Move(file, destination);
}
}
System.IO is your friend in this case ;)
First, Determine file name by:
String filename = System.IO.Path.GetFileNameWithoutExtension(SOME_PATH)
To make path to new folder, use Path.Combine:
String targetDir = Path.Combine(SOME_ROOT_DIR,filename);
Next, create folder with name based on given fileName
System.IO.Directory.CreateDirectory(targetDir);
Ah! You need to have name of file, but with extension this time. Path.GetFileName:
String fileNameWithExtension = System.IO.Path.GetFileName(SOME_PATH);
And you can move file (by File.Move) to it:
System.IO.File.Move(SOME_PATH,Path.Combine(targetDir,fileNameWithExtension)
Laster already show you how to get file list in folder.
I personally prefer DirectoryInfo because it is more object-oriented.
DirectoryInfo sourceDirectory = new DirectoryInfo("C:\MySourceDirectoryPath");
String strTargetDirectory = "C:\MyTargetDirectoryPath";
foreach (FileInfo file in sourceDirectory.GetFiles())
{
file.MoveTo(strTargetDirectory + "\\" + file.Name);
}

Categories