Java IO Tutorial

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

About Author

author image
Founder of Mkyong.com, love Java and open source stuff. Follow him on Twitter. If you like my tutorials, consider make a donation to these charities.

Comments

Subscribe
Notify of
22 Comments
Most Voted
Newest Oldest
Inline Feedbacks
View all comments
vijaya
8 years ago

thank you….

Rajasekhar Pasaleti
9 years ago

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

Abhinandan
4 years ago

I am having the following error:- Could not find or load the main class CopyDirectory

SJ
8 years ago

Thanks man! This is very helpful!

ADHIRAJ KESHRI
8 years ago

Thank you so much Buddy.

Prem Pratick Kumar
9 years ago

Very useful code. very handy

Prem Pratick Kumar

Lamine
9 years ago

Thank you a lot you helps me.

Nikhil Mishra
10 years ago

Hi mkyong,
There is any way of Cut & Paste in same Directory like Windows do (only changing path if same directory)

Tejas
10 years ago

Hi mkyong,
Thanks for this piece of code. It really is useful.
Regards,
Tejas

Gaurav
10 years ago

The code wont’t work if the destination folder is changed to c:\\mkyong-new\\NewfolderA

Sameer
11 years ago

How do we test the copying on directory using JUnit?
I am using FileUtils of Apache Commons IO API.
Please explain.

Tom
11 years ago

The code works great but if it has to be copied from one server to another, having a try catch block when copying would be beneficial

Kamal
11 years ago

Hi, Thanks for this. Can you let me know how to copy directories and files from one server to another server

John Dick
11 years ago

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();
    	        }
 
    	}
}
Dimitris Andreou
13 years ago

To be resolved in Java 7 (hopefully, and at last!)

http://openjdk.java.net/projects/nio/presentations/TS-5686.pdf

Chris
13 years ago

For copying files, FileChannel.transferTo() is much faster.

John
13 years ago

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.

zeja
13 years ago

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.

vivek
11 years ago
Reply to  mkyong

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