How to copy directory in Java

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/mkyong/test/ to /home/mkyong/test2/.

Terminal

$ tree /home/mkyong/test
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

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

TreeCopyFileVisitor.java

package com.mkyong.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) {
        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.mkyong.io.howto;

import com.mkyong.io.utils.TreeCopyFileVisitor;

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

public class CopyDirectory1 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/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

Terminal

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

Check the new directory.

Terminal

$ tree /home/mkyong/test2
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

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>

import org.apache.commons.io.FileUtils;

  //...

  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.mkyong.io.howto;

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;

public class CopyDirectory3 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/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.mkyong.io.howto;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
import java.util.stream.Stream;

public class CopyDirectory4 {

    public static void main(String[] args) {

        String fromDirectory = "/home/mkyong/test/";
        String toToDirectory = "/home/mkyong/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/mkyong/core-java

$ cd java-io

References

22 comments on “How to copy directory in Java

  1. FileUtils.copyDirectory(lSrc, lDest);
    This could also serve better.
    Simple and faster.
    Hope this helps.

  2. Thanks so much for this. I needed to empty my destination directory before copying to restore it to a controlled condition, so I modified your code to make an additional utility to do that. Here it is.

    public static void emptyFolder(File dest)
        	throws IOException{
     
        	if(dest.isDirectory()){
     
        		//if directory exists, delete the files it contains
        		if(dest.exists()){
     
        		//list all the directory contents
        		String files[] = dest.list();
     
        		for (String file : files) {
        		   //construct the dest file structure
        		   File destFile = new File(dest, file);
        		   //recursive delete
        		   emptyFolder(destFile);
        			}
    		}
     
        	}else{
        		//if file, then delete it
    		dest.delete();
        	        }
     
        	}
    }
    
  3. If there’s an error, I usually exit with an error code different than 0. This way you could check for it in a script, or other program.

  4. Hi, why don’t you use an existing API like the apache commons IO FileUtils?

    Some suggestions for your code:

    Never use System.exit(). I can’t remember a case where it’s actually needed.

    Better use mkdirs instead of mkdir to create a directory if you’re not sure that the parent directories do already exist. And check the return value. Sometimes it will return false. You may throw an IOException in this case.

    File.list may return null. Better check for it.

    Always use try-finally when dealing with resource which have to be closed. If an error occurs in your code while copying the files, the streams remain open and my cause you problems afterwards.

    1. This is a demonstration to show the use of pure Java to copy a whole directory, good for practice and learning purpose only.

      In production, the common FileUtils should be always recommended, and your suggestions will definitely bring much extra values for this article. Thanks and appreciate your sharing.

      1. C:\demo\myfile1.txt,myfile.txt,myfile2.txt,myfile3.txt………….
        C:\demo2\myfile1.txt,myfile.txt,myfile2.txt,myfile3.txt………….
        here demo and demo2 are child directories which have same files but different data ,i want to merge (demo)myfile1+(demo2)myfile1 and create a file myfile1 at parent directory c:\demo3 please help

Leave a Comment

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