Skip to content
Advertisement

Rename all files inside subdirectories and place it in their respective parent directory in destination folder

I have below folder structure

.
└── sample/
    ├── A-Star/
    │   ├── bonnet.png
    │   ├── center of front bumper.png
    │   └── center of rear bumper.png
    ├── Alto/
    │   ├── bonnet.png
    │   ├── center of front bumper.png
    │   └── center of rear bumper.png
    └── Suzuki/
        ├── bonnet.png
        ├── center of front bumper.png
        └── center of rear bumper.png  

I want to loop directory one by one and then convert the filename into uppercase, for single word like bonnet.png it should be BONNET.png, but for filename having spaces like center of front bumper, it should be CENTER_OF_FRONT_BUMPER.png.

the output should be like below

.
└── sample/
    ├── A-Star/
    │   ├── bonnet.png
    │   ├── center of front bumper.png
    │   └── center of rear bumper.png
    ├── Alto/
    │   ├── bonnet.png
    │   ├── center of front bumper.png
    │   └── center of rear bumper.png
    ├── Suzuki/
    │   ├── bonnet.png
    │   ├── center of front bumper.png
    │   └── center of rear bumper.png
    └── output/
        ├── A-Star/
        │   ├── BONNET.png
        │   ├── CENTER_OF_FRONT_BUMPER.png
        │   └── CENTER_OF_REAR_BUMPER.png
        ├── Alto/
        │   ├── BONNET.png
        │   ├── CENTER_OF_FRONT_BUMPER.png
        │   └── CENTER_OF_REAR_BUMPER.png
        └── Suzuki/
            ├── BONNET.png
            ├── CENTER_OF_FRONT_BUMPER.png
            └── CENTER_OF_REAR_BUMPER.png

I have written a below code but it is not working as per expectaiton.

firstly it able to make the filename in uppercase(not appended underscore), but it doesn’t create the parent directory and without creating the parent directory it copies the files inside that.

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

public class Test {
    public void listFiles(String startDir) throws IOException {
        File dir = new File(startDir);
        File[] files = dir.listFiles();

        if (files != null && files.length > 0) {
            for (File file : files) {
                // Check if the file is a directory
                if (file.isDirectory()) {
                    // We will not print the directory name, just use it as a new
                    // starting point to list files from
                    listFiles(file.getAbsolutePath());
//                    Path source = file.toPath();
//                    Files.move(source, source.resolveSibling(file.getName().toUpperCase()));
                } else {
                    String path = "D:" + File.separator + "sample" + File.separator + "After Rename";
                    // Use relative path for Unix systems
                    File f = new File(path);
                    f.getParentFile().mkdirs(); 
                    f.createNewFile();
           
                    // We can use .length() to get the file size
//                  String DestinationPath="D:\sample\After Rename";
                    Path source = file.toPath();
                    File oldFile = new File(source.toString());
                    file.getParentFile().mkdirs(); 
                    file.createNewFile();
                    file.getName().toUpperCase();
//                    File newFile = new File(path,file);
////                    Files.move(source, source.resolveSibling(file.getName().toUpperCase()));
//                    oldFile.renameTo(newFile);
                    System.out.println(""+oldFile.getName());
//                    System.out.println(file.getName() + " (size in bytes: " + file.length()+")");
                }
            }
        }
    }
    public static void main(String[] args) throws IOException {
        Test test = new Test();
        String startDir = ("D:\sample");
        test.listFiles(startDir);
    }
}

Advertisement

Answer

Using File and recursive File.listFiles() makes the logic harder to follow. Consider switching to Files.find which can produce a directory scan with a small amount of code:

public static void main(String[] args) throws IOException {

    Path src = Path.of(args[0]);
    Path dst = Path.of(args[1]);

    try (Stream<Path> stream = Files.find(src, Integer.MAX_VALUE, (path, attr) -> attr.isRegularFile())) {
        stream.forEach(System.out::println);
    }
}

The above just prints names of files to process. Then you can swap the action for something that performs the rename, and can be adjusted to apply the action constructing directories before copying:

try (Stream<Path> stream = Files.find(src, Integer.MAX_VALUE, (path, attr) -> attr.isRegularFile())) {
    stream.forEach(file -> {
        // Work out new file name converting basename to uppercase:
        String fn = file.getFileName().toString();
        int dot = fn.lastIndexOf('.');
        if (dot > 0)
            fn = fn.substring(0,dot).toUpperCase().replace(' ', '_') + fn.substring(dot);

        // Work out where to copy the new file under the same path of the dst directory:
        Path target = dst.resolve(src.relativize(file)).resolveSibling(fn);
            System.out.println("Files.createDirectories("+target.getParent()+");");
            System.out.println("Files.copy("+file+"," + target+");");
            /**
            // TODO:
            try
            {
                Files.createDirectories(target.getParent());
                Files.copy(file,target);
            }
            catch (IOException e)
            {
                throw new UncheckedIOException(e);
            }
             */
    });
}

It’s never a good idea to generate files into the directory you scan – as that means you cannot re-run on same input as you will be doubling the number of files.

User contributions licensed under: CC BY-SA
10 People found this is helpful
Advertisement