Cambia automáticamente el nombre de un archivo si ya existe en Windows

Mi código C # genera varios archivos de texto basados ​​en la entrada y los guarda en una carpeta. Además, supongo que el nombre del archivo de texto será el mismo que el de entrada. (La entrada contiene solo letras) Si dos archivos tienen el mismo nombre, simplemente está sobrescribiendo el archivo anterior. Pero quiero conservar ambos archivos.

No deseo agregar la fecha actual o un número aleatorio al segundo nombre de archivo. En cambio, quiero hacerlo de la misma manera que lo hace Windows. Si el nombre del archivo fisrt es AAA.txt, entonces el segundo nombre de archivo es AAA (2) .txt, el tercer nombre de archivo será AAA (3) .txt ….. El nombre del archivo N será AAA (N) .txt .

string[] allFiles = Directory.GetFiles(folderPath).Select(filename => Path.GetFileNameWithoutExtension(filename)).ToArray(); foreach (var item in allFiles) { //newFileName is the txt file which is going to be saved in the provided folder if (newFileName.Equals(item, StringComparison.InvariantCultureIgnoreCase)) { // What to do here ? } } 

Esto verificará la existencia de archivos con tempFileName e incrementará el número uno hasta que encuentre un nombre que no existe en el directorio.

 int count = 1; string fileNameOnly = Path.GetFileNameWithoutExtension(fullPath); string extension = Path.GetExtension(fullPath); string path = Path.GetDirectoryName(fullPath); string newFullPath = fullPath; while(File.Exists(newFullPath)) { string tempFileName = string.Format("{0}({1})", fileNameOnly, count++); newFullPath = Path.Combine(path, tempFileName + extension); } 

Con este código, si filename es “Test (3) .txt”, se convertirá en “Test (4) .txt”.

 public static string GetUniqueFilePath(string filepath) { if (File.Exists(filepath)) { string folder = Path.GetDirectoryName(filepath); string filename = Path.GetFileNameWithoutExtension(filepath); string extension = Path.GetExtension(filepath); int number = 1; Match regex = Regex.Match(filepath, @"(.+) \((\d+)\)\.\w+"); if (regex.Success) { filename = regex.Groups[1].Value; number = int.Parse(regex.Groups[2].Value); } do { number++; filepath = Path.Combine(folder, string.Format("{0} ({1}){2}", filename, number, extension)); } while (File.Exists(filepath)); } return filepath; } 

Los otros ejemplos no tienen en cuenta el nombre de archivo / extensión.

Aqui tienes:

  public static string GetUniqueFilename(string fullPath) { if (!Path.IsPathRooted(fullPath)) fullPath = Path.GetFullPath(fullPath); if (File.Exists(fullPath)) { String filename = Path.GetFileName(fullPath); String path = fullPath.Substring(0, fullPath.Length - filename.Length); String filenameWOExt = Path.GetFileNameWithoutExtension(fullPath); String ext = Path.GetExtension(fullPath); int n = 1; do { fullPath = Path.Combine(path, String.Format("{0} ({1}){2}", filenameWOExt, (n++), ext)); } while (File.Exists(fullPath)); } return fullPath; } 

¿Qué tal solo?

 int count = 1; String tempFileName = newFileName; foreach (var item in allFiles) { if (tempFileName.Equals(item, StringComparison.InvariantCultureIgnoreCase)) { tempFileName = String.Format("{0}({1})", newFileName, count++); } } 

Esto utilizará el nombre del archivo original si no está allí, de lo contrario tomará un nuevo nombre de archivo con el índice entre corchetes (aunque este código no tiene en cuenta la extensión). Si se utiliza el nombre recién generado “texto (001)”, boostá hasta que encuentre un nombre de archivo válido no utilizado.

 public static string AutoRenameFilename(FileInfo file) { var filename = file.Name.Replace(file.Extension, string.Empty); var dir = file.Directory.FullName; var ext = file.Extension; if (file.Exists) { int count = 0; string added; do { count++; added = "(" + count + ")"; } while (File.Exists(dir + "\\" + filename + " " + added + ext)); filename += " " + added; } return (dir + filename + ext); } 

Estaba buscando una solución que movería un archivo, y me aseguro de que el nombre del archivo de destino no esté ya ocupado. Seguiría la misma lógica que Windows y anexará un número, con corchetes después del archivo duplicado.

La respuesta principal, gracias a @ cadrell0, me ayudó a llegar a la siguiente solución:

  ///  /// 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. /// /// Eg 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 /// ///  /// Eg D:\DestinationDir  /// D:\Source\file.txt ///  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; } 

Puede declarar un Dictionary para mantener el número de veces que se guardó cada nombre de archivo raíz. Después de eso, en su método Save , simplemente incremente el contador y añádalo al nombre del archivo base:

 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]) } 

De esta forma, tendrá un contador para cada nombre de archivo distinto: AAA (1), AAA (2); BBB (1) …

Está funcionando bien ahora. gracias chicos por las respuestas ..

 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; 

archivo es el nombre del archivo

 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++; } 

Con respecto al comentario de Giuseppe sobre la forma en que Windows cambia el nombre de los archivos, trabajé en una versión que encuentra cualquier índice existente, es decir, (2) en el nombre del archivo y renombra el archivo de acuerdo con Windows. Se supone que el SourceFileName es válido y se supone que el usuario tiene permiso de escritura en la carpeta de destino en este punto:

 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); }