86

Method to copy entire directory contents to another directory in java or groovy?

Lernkurve
  • 20,203
  • 28
  • 86
  • 118
Sanal MS
  • 2,424
  • 4
  • 24
  • 31

10 Answers10

121

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();
}
Fangming
  • 24,551
  • 6
  • 100
  • 90
jmj
  • 237,923
  • 42
  • 401
  • 438
34

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;
        }
    });
Archimedes Trajano
  • 35,625
  • 19
  • 175
  • 265
  • There is actually a visitor by the oracle guys for this job: http://docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java - what are the differences with yours ? – Mr_and_Mrs_D Apr 17 '14 at 16:13
  • 2
    Mine just copies the files, theirs is a full app with copying of attributes. – Archimedes Trajano Apr 17 '14 at 20:22
  • Very nice solution! I'll point out to other readers one of the not so obvious advantage to this approach. This approach can be used to copy files in and out of jars, if you use a jar FileSystem path. – Tom Rutchik Feb 12 '22 at 16:37
16

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.

Sergey Ushakov
  • 2,425
  • 1
  • 24
  • 15
tim_yates
  • 167,322
  • 27
  • 342
  • 338
  • 8
    You probably can in Java, but it is like using a sledge-hammer to crack a walnut. – Stephen C Jun 02 '11 at 13:45
  • 1
    Perhaps, but in groovy AntBuilder is part of the distribution and the automatic imports list which means it is directly available for any groovy code as written in the answer. – Matias Bjarland Feb 06 '17 at 11:52
13
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();
            }
        }
    }
}
kayz1
  • 7,260
  • 3
  • 53
  • 56
  • Is it Groovy? It looks even more C++ than Java. :-). But it seems correct. +1. It is good if we are copying and simultaneously doing some work with text being copied. – Gangnus Oct 23 '15 at 16:28
  • Works, simple, good! The only difference between this solution and perhaps others is the date modified and date created of the copy are set to the current time, but sometimes that's what you want anyway. – Perry Monschau Oct 24 '17 at 14:14
  • 3
    Call me old fashioned, but it's great to see curly brackets on new lines. I'm an ex C and C++ programmer and, even though I've written in Java for 20 years, I still write code like this. Much more readable! – DAB Mar 12 '21 at 16:34
  • I think this is the clearer approach. What about with a progress bar ? – Noor Hossain Oct 08 '21 at 14:22
  • life saver I use it in kotlin WORKS PERFECT +2 – Amir Jan 19 '22 at 15:10
8

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)
    }
}
Gangnus
  • 24,044
  • 16
  • 90
  • 149
  • 2
    How is this better than `FileUtils.copyDirectory()`? – doelleri Oct 23 '15 at 16:17
  • 4
    @doelleri It is better in two points - I needn't install any additional jars or put references in Maven, struggling with versions. BTW, that "answer" should have appropriate include line and reference to the jar. The second reason - if I want to have some serious filtration in daughter dirs, only my code will help. The third reason - here is the site for programmers, not merely SW users. :-) – Gangnus Oct 23 '15 at 16:26
  • You can replace FILES with groovy.io.FileType.FILES and DIRECTORIES with groovy.io.FileType.DIRECTORIES if you are wondering where those come from. – Luke Machowski Jul 27 '20 at 14:57
5
seeker
  • 671
  • 7
  • 13
planetjones
  • 12,469
  • 5
  • 50
  • 51
4

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();
        }

    }

}
Charlie
  • 8,530
  • 2
  • 55
  • 53
Mohit Kanwar
  • 2,962
  • 7
  • 39
  • 59
  • 1
    why the downvote.. ? Please suggest if some improvement is desired. – Mohit Kanwar Jun 22 '17 at 05:57
  • The string replace may cause unintended side effects. You should only replace the very beginning, which we know exists, and we know it's length, so you could just use: Paths.get(dest, a.toString().substring(src.length())). Also, there are a few optimizations you could make: the duplicate FileAlreadyExistsException clause could be removed, you only have one usage of both the source and destination Path objects so there's no need to have a var for each – Charlie Feb 06 '18 at 06:45
  • Agreed, thankyou @Charlie – Mohit Kanwar Feb 06 '18 at 07:34
  • I would have suggested swapping out some boilerplate for lambdas but that will hurt people looking for Java 7 (6?) answers. – Charlie Feb 06 '18 at 07:40
  • I was going to add my own answer but this question was closed as a dupe (even though it isn't). I'll add to your answer with my Java 9 version. Delete it if you don't like it ;) – Charlie Feb 06 '18 at 08:02
  • Sorry for the spam, there's another issue with the original implementation; it throws some exceptions (although actually does the copy) because the top-level of the directory being walked (./) is included in the result stream, causing a java.nio.file.DirectoryNotEmptyException. See my updated version for a check to prevent it and feel free to add to your original version. – Charlie Feb 06 '18 at 08:06
3

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.

Community
  • 1
  • 1
Gili
  • 86,244
  • 97
  • 390
  • 689
  • 1
    Please correct the link (the method is here : http://commons.apache.org/proper/commons-io/apidocs/org/apache/commons/io/FileUtils.html#copyDirectory%28java.io.File,%20java.io.File%29) but I guess you linked to the code – Mr_and_Mrs_D Apr 18 '14 at 12:48
0

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

Peter
  • 1,182
  • 2
  • 12
  • 23
0

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

Community
  • 1
  • 1
mre
  • 43,520
  • 33
  • 120
  • 170