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.
FileVisitor(Java 7+)FileUtils.copyDirectory(Apache commons-io)- Custom Copy using Java 7 NIO and Java 8 Stream.
- Custom Copy, legacy IO.
Note
The NIOFiles.copydoes 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