将整个目录内容复制到另一个目录?

方法将整个目录内容复制到 Java 或 Groovy 中的另一个目录?

179395 次浏览

FileUtils.copyDirectory()

Copies a whole directory to a new location preserving the file dates. This method copies the specified directory and all its child directories and files to the specified destination. The destination is the new location and name of the directory.

The destination directory is created if it does not exist. If the destination directory did exist, then this method merges the source with the destination, with the source taking precedence.

To do so, here's the example code

String source = "C:/your/source";
File srcDir = new File(source);


String destination = "C:/your/destination";
File destDir = new File(destination);


try {
FileUtils.copyDirectory(srcDir, destDir);
} catch (IOException e) {
e.printStackTrace();
}

With regard to Java, there is no such method in the standard API. In Java 7, the java.nio.file.Files class will provide a copy convenience method.

References

  1. The Java Tutorials

  2. Copying files from one directory to another in Java

With Groovy, you can leverage Ant to do:

new AntBuilder().copy( todir:'/path/to/destination/folder' ) {
fileset( dir:'/path/to/src/folder' )
}

AntBuilder is part of the distribution and the automatic imports list which means it is directly available for any groovy code.

The following is an example of using JDK7.

public class CopyFileVisitor extends SimpleFileVisitor<Path> {
private final Path targetPath;
private Path sourcePath = null;
public CopyFileVisitor(Path targetPath) {
this.targetPath = targetPath;
}


@Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs) throws IOException {
if (sourcePath == null) {
sourcePath = dir;
} else {
Files.createDirectories(targetPath.resolve(sourcePath
.relativize(dir)));
}
return FileVisitResult.CONTINUE;
}


@Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs) throws IOException {
Files.copy(file,
targetPath.resolve(sourcePath.relativize(file)));
return FileVisitResult.CONTINUE;
}
}

To use the visitor do the following

Files.walkFileTree(sourcePath, new CopyFileVisitor(targetPath));

If you'd rather just inline everything (not too efficient if you use it often, but good for quickies)

    final Path targetPath = // target
final Path sourcePath = // source
Files.walkFileTree(sourcePath, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs) throws IOException {
Files.createDirectories(targetPath.resolve(sourcePath
.relativize(dir)));
return FileVisitResult.CONTINUE;
}


@Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs) throws IOException {
Files.copy(file,
targetPath.resolve(sourcePath.relativize(file)));
return FileVisitResult.CONTINUE;
}
});

Neither FileUtils.copyDirectory() nor Archimedes's answer copy directory attributes (file owner, permissions, modification times, etc).

https://stackoverflow.com/a/18691793/14731 provides a complete JDK7 solution that does precisely that.

public static void copyFolder(File source, File destination)
{
if (source.isDirectory())
{
if (!destination.exists())
{
destination.mkdirs();
}


String files[] = source.list();


for (String file : files)
{
File srcFile = new File(source, file);
File destFile = new File(destination, file);


copyFolder(srcFile, destFile);
}
}
else
{
InputStream in = null;
OutputStream out = null;


try
{
in = new FileInputStream(source);
out = new FileOutputStream(destination);


byte[] buffer = new byte[1024];


int length;
while ((length = in.read(buffer)) > 0)
{
out.write(buffer, 0, length);
}
}
catch (Exception e)
{
try
{
in.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}


try
{
out.close();
}
catch (IOException e1)
{
e1.printStackTrace();
}
}
}
}

If you're open to using a 3rd party library, check out javaxt-core. The javaxt.io.Directory class can be used to copy directories like this:

javaxt.io.Directory input = new javaxt.io.Directory("/source");
javaxt.io.Directory output = new javaxt.io.Directory("/destination");
input.copyTo(output, true); //true to overwrite any existing files

You can also provide a file filter to specify which files you want to copy. There are more examples here:

http://javaxt.com/javaxt-core/io/Directory/Directory_Copy

This is my piece of Groovy code for that. Tested.

private static void copyLargeDir(File dirFrom, File dirTo){
// creation the target dir
if (!dirTo.exists()){
dirTo.mkdir();
}
// copying the daughter files
dirFrom.eachFile(FILES){File source ->
File target = new File(dirTo,source.getName());
target.bytes = source.bytes;
}
// copying the daughter dirs - recursion
dirFrom.eachFile(DIRECTORIES){File source ->
File target = new File(dirTo,source.getName());
copyLargeDir(source, target)
}
}

With coming in of Java NIO, below is a possible solution too

With Java 9:

private static void copyDir(String src, String dest, boolean overwrite) {
try {
Files.walk(Paths.get(src)).forEach(a -> {
Path b = Paths.get(dest, a.toString().substring(src.length()));
try {
if (!a.toString().equals(src))
Files.copy(a, b, overwrite ? new CopyOption[]{StandardCopyOption.REPLACE_EXISTING} : new CopyOption[]{});
} catch (IOException e) {
e.printStackTrace();
}
});
} catch (IOException e) {
//permission issue
e.printStackTrace();
}
}

With Java 7:

import java.io.IOException;
import java.nio.file.FileAlreadyExistsException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.function.Consumer;
import java.util.stream.Stream;


public class Test {


public static void main(String[] args) {
Path sourceParentFolder = Paths.get("/sourceParent");
Path destinationParentFolder = Paths.get("/destination/");


try {
Stream<Path> allFilesPathStream = Files.walk(sourceParentFolder);
Consumer<? super Path> action = new Consumer<Path>(){


@Override
public void accept(Path t) {
try {
String destinationPath = t.toString().replaceAll(sourceParentFolder.toString(), destinationParentFolder.toString());
Files.copy(t, Paths.get(destinationPath));
}
catch(FileAlreadyExistsException e){
//TODO do acc to business needs
}
catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}


}


};
allFilesPathStream.forEach(action );


} catch(FileAlreadyExistsException e) {
//file already exists and unable to copy
} catch (IOException e) {
//permission issue
e.printStackTrace();
}


}


}