My C# code is generating several text files based on input and saving those in a folder. Also, I am assuming that the name of the text file will be same as input.(The input
How about just:
int count = 1;
String tempFileName = newFileName;
foreach (var item in allFiles)
{
if (tempFileName.Equals(item, StringComparison.InvariantCultureIgnoreCase))
{
tempFileName = String.Format("{0}({1})", newFileName, count++);
}
}
This will use the original file name if it's not there, if not it'll take a new file name with the index in brackets (although this code isn't taking the extension into account). If the newly generated name "text(001)" is used then it'll increment until it finds a valid unused file name.
With regard to Giuseppe's comment on the way windows renames files I worked on a version that finds any existing index i.e. (2) in the file name and renames the file as per windows accordingly. The sourceFileName is assumed to be valid and the user is assumed to have write permission on the destination folder by this point:
using System.IO;
using System.Text.RegularExpressions;
private void RenameDiskFileToMSUnique(string sourceFileName)
{
string destFileName = "";
long n = 1;
// ensure the full path is qualified
if (!Path.IsPathRooted(sourceFileName)) { sourceFileName = Path.GetFullPath(sourceFileName); }
string filepath = Path.GetDirectoryName(sourceFileName);
string fileNameWOExt = Path.GetFileNameWithoutExtension(sourceFileName);
string fileNameSuffix = "";
string fileNameExt = Path.GetExtension(sourceFileName);
// if the name includes the text "(0-9)" then we have a filename, instance number and suffix
Regex r = new Regex(@"\(\d+\)");
Match match = r.Match(fileNameWOExt);
if (match.Success) // the pattern (0-9) was found
{
// text after the match
if (fileNameWOExt.Length > match.Index + match.Length) // remove the format and create the suffix
{
fileNameSuffix = fileNameWOExt.Substring(match.Index + match.Length, fileNameWOExt.Length - (match.Index + match.Length));
fileNameWOExt = fileNameWOExt.Substring(0, match.Index);
}
else // remove the format at the end
{
fileNameWOExt = fileNameWOExt.Substring(0, fileNameWOExt.Length - match.Length);
}
// increment the numeric in the name
n = Convert.ToInt64(match.Value.Substring(1, match.Length - 2)) + 1;
}
// format variation: indexed text retains the original layout, new suffixed text inserts a space!
do
{
if (match.Success) // the text was already indexed
{
if (fileNameSuffix.Length > 0)
{
destFileName = Path.Combine(filepath, String.Format("{0}({1}){2}{3}", fileNameWOExt, (n++), fileNameSuffix, fileNameExt));
}
else
{
destFileName = Path.Combine(filepath, String.Format("{0}({1}){2}", fileNameWOExt, (n++), fileNameExt));
}
}
else // we are adding a new index
{
destFileName = Path.Combine(filepath, String.Format("{0} ({1}){2}", fileNameWOExt, (n++), fileNameExt));
}
}
while (File.Exists(destFileName));
File.Copy(sourceFileName, destFileName);
}
It's working fine now. thanks guys for the answers..
string[] allFiles = Directory.GetFiles(folderPath).Select(filename => Path.GetFileNameWithoutExtension(filename)).ToArray();
string tempFileName = fileName;
int count = 1;
while (allFiles.Contains(tempFileName ))
{
tempFileName = String.Format("{0} ({1})", fileName, count++);
}
output = Path.Combine(folderPath, tempFileName );
string fullPath=output + ".xml";
int count= 0;
file is the name of file
while (File.Exists(fullpathwithfilename)) //this will check for existence of file
{
// below line names new file from file.xls to file1.xls
fullpathwithfilename= fullpathwithfilename.Replace("file.xls", "file"+count+".xls");
count++;
}
I was looking for a solution that would move a file, and make sure that if the destination file name is not already taken. It would follow the same logic as Windows and append a number, with brackets after the duplicate file.
The top answer, thanks to @cadrell0, helped me arrive to the following solution:
/// <summary>
/// Generates full file path for a file that is to be moved to a destinationFolderDir.
///
/// This method takes into account the possiblity of the file already existing,
/// and will append number surrounded with brackets to the file name.
///
/// E.g. if D:\DestinationDir contains file name file.txt,
/// and your fileToMoveFullPath is D:\Source\file.txt, the generated path will be D:\DestinationDir\file(1).txt
///
/// </summary>
/// <param name="destinationFolderDir">E.g. D:\DestinationDir </param>
/// <param name="fileToMoveFullPath">D:\Source\file.txt</param>
/// <returns></returns>
public string GetFullFilePathWithDuplicatesTakenInMind(string destinationFolderDir, string fileToMoveFullPath)
{
string destinationPathWithDuplicatesTakenInMind;
string fileNameWithExtension = Path.GetFileName(fileToMoveFullPath);
string fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileToMoveFullPath);
string fileNameExtension = Path.GetExtension(fileToMoveFullPath);
destinationPathWithDuplicatesTakenInMind = Path.Combine(destinationFolderDir, fileNameWithExtension);
int count = 0;
while (File.Exists(destinationPathWithDuplicatesTakenInMind))
{
destinationPathWithDuplicatesTakenInMind = Path.Combine(destinationFolderDir, $"{fileNameWithoutExtension}({count}){fileNameExtension}");
count = count + 1; // sorry, not a fan of the ++ operator.
}
return destinationPathWithDuplicatesTakenInMind;
}
You can declare a Dictionary<string,int>
to keep the number of times each root file name was saved. After that, on your Save
method, just increase the counter and append it to the base file name:
var key = fileName.ToLower();
string newFileName;
if(!_dictionary.ContainsKey(key))
{
newFileName = fileName;
_dictionary.Add(key,0);
}
else
{
_dictionary[key]++;
newFileName = String.Format("{0}({1})", fileName, _dictionary[key])
}
This way, you'll have a counter for each distinct file name: AAA(1), AAA(2); BBB(1)...