1

I need to rename a file.

Path destPath = Paths.get(directoryPath, hash);
Files.move(path, destPath);

The problem is that when I'm trying to "rename" the file, it can already exist.

Is there anyway to solve it by convention adding a suffix like -number?

For example, if I need to rename to newfile and newfile and newfile1 exist, I want to rename to rename2.

If at the time to rename newfile2 file, another file is renamed to newfile2 then newfile3 should be written...

Any ideas?

Jordi
  • 20,868
  • 39
  • 149
  • 333
  • 1
    originalName; newName = originalName; counter 0; while (newName.exists()) newName = originalName -> add (++counter) as suffix; – Stultuske Apr 17 '23 at 10:23
  • The best is instead of a number add a timestamp, then it will always be unique and incremental – Farrukh Nabiyev Apr 17 '23 at 13:14
  • Is there a reason you can’t build the new destination path yourself? If the path exists, use `hash + "-" + number`. Write a loop that, as long the path exists, increments the number and builds a new destination path. – VGR Apr 17 '23 at 13:36

1 Answers1

-1

A source file can be moved to a target directory (targetDir) and will rename the file when the filename already exists in the target directory. Not thoroughly tested though.

package testcode;

import java.io.File;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;

public class TestCode {

    public static void main(String[] args) {
        
        String dir = "C:"+File.separator+"Users"+File.separator+"Name"+File.separator+"Documents"+File.separator;
        String fileName = "filename.ext";
        String fileLocation = dir+fileName;
        Path source = Paths.get(fileLocation);
        String targetDir = source.getParent().toString();        
        
        moveFile(source, targetDir);
    }
       
    private static boolean moveFile(Path source, String targetDir) {
        
        String fileName = removeExtension(source.getFileName().toString());
        String ext = getFileExtension(source.getFileName().toString());

        String target = targetDir+File.separator+fileName+ext;     
        int count = 1;
        
        while (Files.exists(Paths.get(target))) {
            target = targetDir+File.separator+fileName+count+ext;     
            count++;
        }
            
        try {             
            Files.move(source, Paths.get(target));
            System.out.print("Moved file");
            return true;                
        } 
        catch (Exception e) {
            e.printStackTrace();
        }  
         
        return false;
    }
    
    private static String getFileExtension(String fileName) {
        int index = fileName.lastIndexOf('.');
        if (index > 0) {
            return fileName.substring(index);
        }
        return null;
    }
    
    private static String removeExtension(String fileName) {
        int index = fileName.lastIndexOf('.');
        if (index > 0) {
            return fileName.substring(0, index);
        }       
        return null;
    }

}
vaultboy
  • 173
  • 1
  • 1
  • 12
  • 1
    By the way it's pointless using `File.separator` here as you have mentioned "C:" - Java on Windows accepts \ or / in paths (easier just to use / everywhere as it is quicker to type than \\\). Code that relies on `File.separator` as the trailing character with string concatenation is brittle - it is easy to forget. Instead note that `Paths.get` / `Path.of` both accept multiple components so the separator is not needed. – DuncG Apr 17 '23 at 20:46
  • 1
    This code is a typical example of the *check-then-act* anti-pattern. There is no guaranty that the file still doesn’t exist when you call `move` at some time *after* the `exists` check. The `move` method takes care of that anyway, it will throw a `FileAlreadyExistsException` when the target file already exists but your code handles it by just returning `false`, defeating the entire purpose of the method. Generally, you should rethink how you deal with errors. Your methods return `null` when there’s no dot in the name, then you proceed with that result, producing file names like `"nullnull"`… – Holger Jun 13 '23 at 15:59
  • @Holger Sure, I fully agree. My code is only a sloppy rough setup that answers an imporant part of the problem. What I meant with it not being tested is that the problems you mention can be quite easily found and fixed after testing it. – vaultboy Jun 14 '23 at 20:58