In Java, we can use the Java 1.7 FileVisitor or Apache Commons IO FileUtils.copyDirectory to copy a directory, which includes its sub-directories and files.

This article shows a few of the common ways to copy a directory in Java.

  1. FileVisitor (Java 7+)
  2. FileUtils.copyDirectory (Apache commons-io)
  3. Custom Copy using Java 7 NIO and Java 8 Stream.
  4. Custom Copy, legacy IO.

Note
The NIO Files.copy does not support copying directory contents, and we need to create a customized method to copy the directory contents.

1. FileVisitor (Java 7)

This example shows how to use FileVisitor to copy directory and its content from /home/tvt/workspace/favtuts/test/ to /home/tvt/workspace/favtuts/test2/.

$ tree /home/tvt/workspace/favtuts/test
/home/tvt/workspace/favtuts/test
├── test-a1.log
├── test-a2.log
└── test-b
    ├── test-b1.txt
    ├── test-b2.txt
    ├── test-c
    │   ├── test-c1.log
    │   └── test-c2.log
    └── test-d
        ├── test-d1.log
        └── test-d2.log

3 directories, 8 files

1.1 This class extends SimpleFileVisitor to provide defaults and override only necessary methods.

TreeCopyFileVisitor.java

package com.favtuts.io.utils;

import java.io.IOException;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;

public class TreeCopyFileVisitor extends SimpleFileVisitor<Path> {

    private Path source;
    private final Path target;

    public TreeCopyFileVisitor(String source, String target) {
        this.source = Paths.get(source);
        this.target = Paths.get(target);
    }

    @Override
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
        
        Path resolve = target.resolve(source.relativize(dir));
        if (Files.notExists(resolve)) {
            Files.createDirectories(resolve);
            System.out.println("Create directories : " + resolve);
        }
        return FileVisitResult.CONTINUE;

    }

    @Override
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
        
        Path resolve = target.resolve(source.relativize(file));
        Files.copy(file, resolve, StandardCopyOption.REPLACE_EXISTING);
        System.out.println(
            String.format("Copy File from \t'%s' to \t'%s'", file, resolve)
        );
        return FileVisitResult.CONTINUE;

    }

    @Override
    public FileVisitResult visitFileFailed(Path file, IOException exc) throws IOException {
        System.err.format("Unable to copy: %s: %s%n", file, exc);
        return FileVisitResult.CONTINUE;
    }
    
}

1.2 This example uses Files.walkFileTree to walk the file tree.

CopyDirectory1.java

package com.favtuts.io.howto;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;

import com.favtuts.io.utils.TreeCopyFileVisitor;

public class CopyDirectory {
    
    public static void main(String[] args) {
        String fromDirectory = "/home/tvt/workspace/favtuts/test/";
        String toToDirectory = "/home/tvt/workspace/favtuts/test2/";

        try {

            copyDirectoryFileVisitor(fromDirectory, toToDirectory);
        
        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");
    }


    public static void copyDirectoryFileVisitor(String source, String target) throws IOException {

        TreeCopyFileVisitor fileVisitor = new TreeCopyFileVisitor(source, target);
        Files.walkFileTree(Paths.get(source), fileVisitor);
    }

}

Output

Create directories : /home/tvt/workspace/favtuts/test2
Copy File from  '/home/tvt/workspace/favtuts/test/test-a1.log' to       '/home/tvt/workspace/favtuts/test2/test-a1.log'
Copy File from  '/home/tvt/workspace/favtuts/test/test-a2.log' to       '/home/tvt/workspace/favtuts/test2/test-a2.log'
Create directories : /home/tvt/workspace/favtuts/test2/test-b
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-b2.txt' to        '/home/tvt/workspace/favtuts/test2/test-b/test-b2.txt'
Create directories : /home/tvt/workspace/favtuts/test2/test-b/test-d
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-d/test-d1.log' to         '/home/tvt/workspace/favtuts/test2/test-b/test-d/test-d1.log'
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-d/test-d2.log' to         '/home/tvt/workspace/favtuts/test2/test-b/test-d/test-d2.log'
Create directories : /home/tvt/workspace/favtuts/test2/test-b/test-c
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-c/test-c2.log' to         '/home/tvt/workspace/favtuts/test2/test-b/test-c/test-c2.log'
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-c/test-c1.log' to         '/home/tvt/workspace/favtuts/test2/test-b/test-c/test-c1.log'
Copy File from  '/home/tvt/workspace/favtuts/test/test-b/test-b1.txt' to        '/home/tvt/workspace/favtuts/test2/test-b/test-b1.txt'
Done

Check the new directory.

$ tree /home/tvt/workspace/favtuts/test2
/home/tvt/workspace/favtuts/test2
├── test-a1.log
├── test-a2.log
└── test-b
    ├── test-b1.txt
    ├── test-b2.txt
    ├── test-c
    │   ├── test-c1.log
    │   └── test-c2.log
    └── test-d
        ├── test-d1.log
        └── test-d2.log

3 directories, 8 files

Note

The official Java Copy example copies everything, including the file attribute. However, it is harder to read; this example simplifies the method to only copy files and directories and excludes the attributes.

2. FileUtils.copyDirectory (Apache commons-io)

This example uses FileUtils.copyDirectory to copy a directory and its content, a friendly, and straightforward API.

pom.xml

  <dependency>
      <groupId>commons-io</groupId>
      <artifactId>commons-io</artifactId>
      <version>2.7</version>
  </dependency>

CopyDirectory2.java

package com.favtuts.io.howto;

import java.io.File;
import java.io.IOException;

import com.favtuts.io.utils.TreeCopyFileVisitor;

import org.apache.commons.io.FileUtils;

public class CopyDirectory {

    public static void main(String[] args) {
        String fromDirectory = "/home/tvt/workspace/favtuts/test/";
        String toToDirectory = "/home/tvt/workspace/favtuts/test2/";

        try {

            copyFileCommonIO(fromDirectory, toToDirectory);

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");
    }

    public static void copyFileCommonIO(String from, String to) throws IOException {

        File fromDir = new File(from);
        File toDir = new File(to);

        FileUtils.copyDirectory(fromDir, toDir);

    }
}

3. Java NIO and Stream.

This example uses Java 8 Files.list to simulate a file walker and Java 7 NIO Files to check, create, and copy the directory and its content.

CopyDirectory3.java

package com.favtuts.io.howto;

import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

import com.favtuts.io.utils.TreeCopyFileVisitor;

import org.apache.commons.io.FileUtils;

public class CopyDirectory {

    public static void main(String[] args) {
        String fromDirectory = "/home/tvt/workspace/favtuts/test/";
        String toToDirectory = "/home/tvt/workspace/favtuts/test2/";

        try {

            copyDirectoryJavaNIO(Paths.get(fromDirectory),Paths.get(toToDirectory));

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");
    }

    public static void copyDirectoryJavaNIO(Path source, Path target) throws IOException {

        // is this a directory?
        if (Files.isDirectory(source)) {

            //if target directory exist?
            if (Files.notExists(target)) {
                // create it
                Files.createDirectories(target);
                System.out.println("Directory created : " + target);
            }

            // list all files or folders from the source, Java 1.8, returns a stream
            // doc said need try-with-resources, auto-close stream
            try (Stream<Path> paths = Files.list(source)) {

                // recursive loop
                paths.forEach(p ->
                        copyDirectoryJavaNIOWrapper(
                            p, target.resolve(source.relativize(p)))
                );

            }

        } else {
            // if file exists, replace it
            Files.copy(source, target, StandardCopyOption.REPLACE_EXISTING);
            System.out.println(
                    String.format("Copy File from \t'%s' to \t'%s'", source, target)
            );
        }    
    }

    // extract method to handle exception in lambda
    public static void copyDirectoryJavaNIOWrapper(Path source, Path target) {

        try {
            copyDirectoryJavaNIO(source, target);
        } catch (IOException e) {
            System.err.println("IO errors : " + e.getMessage());
        }

    }
}

4. Legacy IO

This example is similar to method 3. Instead, it sticks with the legacy IO java.io.*, just for reference.

CopyDirectory4.java

package com.favtuts.io.howto;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.stream.Stream;

public class CopyDirectory {

    public static void main(String[] args) {
        String fromDirectory = "/home/tvt/workspace/favtuts/test/";
        String toToDirectory = "/home/tvt/workspace/favtuts/test2/";

        try {

            copyDirectoryLegacyIO(new File(fromDirectory), new File(toToDirectory));

        } catch (IOException e) {
            e.printStackTrace();
        }

        System.out.println("Done");
    }

    public static void copyDirectoryLegacyIO(File source, File target) throws IOException {

        if (source.isDirectory()) {

            //if directory not exists, create it
            if (!target.exists()) {
                if (target.mkdir()) {
                    System.out.println("Directory copied from "
                            + source + "  to " + target);
                } else {
                    System.err.println("Unable to create directory : " + target);
                }
            }

            // list all the directory contents, file walker
            String[] files = source.list();
            if (files == null) {
                return;
            }

            for (String file : files) {
                //construct the src and dest file structure
                File srcFile = new File(source, file);
                File destFile = new File(target, file);
                //recursive copy
                copyDirectoryLegacyIO(srcFile, destFile);
            }

        } else {

            //if file, then copy it
            //Use bytes stream to support all file types
            InputStream in = null;
            OutputStream out = null;

            try {

                in = new FileInputStream(source);
                out = new FileOutputStream(target);

                byte[] buffer = new byte[1024];

                int length;
                //copy the file content in bytes
                while ((length = in.read(buffer)) > 0) {
                    out.write(buffer, 0, length);
                }

                System.out.println("File copied from " + source + " to " + target);

            } catch (IOException e) {

                System.err.println("IO errors : " + e.getMessage());

            } finally {
                if (in != null) {
                    in.close();
                }

                if (out != null) {
                    out.close();
                }
            }
        }

    }
}

Note

Java, after 20+ years, there is still no official API to copy a directory, how hard to create a Files.copyDirectory()?

Download Source Code

$ git clone https://github.com/favtuts/java-core-tutorials-examples

$ cd java-io/file – howto

References

Leave a Reply

Your email address will not be published. Required fields are marked *