Copy entire directory contents to another directory? [duplicate]
Asked Answered
B

10

90

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

Beak answered 2/6, 2011 at 12:48 Comment(1)
You want a command line tool or code?Freund
P
124

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();
}
Primacy answered 2/6, 2011 at 12:51 Comment(8)
In my case I had some subfolders and I also wanted to copy the structure, and found the method FileUtils.copyDirectoryStructure(). Maybe this helps some other people too.Leitao
What about the JAVA API NIO 2 ? I tried Files.copy(Path, Path) but it seems to not do the same job.Coinstantaneous
@Ethan Leroy what difference between copyDirectoryStructure and copyDirectory ?Clearway
As you can see here, "Directories can be copied. However, files inside the directory are not copied, so the new directory is empty" docs.oracle.com/javase/tutorial/essential/io/copy.htmlAlternately
This doesn't use java NIO, thus cannot copy from ZipFileSystemAbsolve
import org.apache.commons.io.FileUtilsUnswear
is this copy all subfolders and their elements also ?Darbydarce
@NoorHossain, yes ("and all its child directories and files")Scuttle
M
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;
        }
    });
Milreis answered 9/4, 2012 at 2:30 Comment(3)
There is actually a visitor by the oracle guys for this job: docs.oracle.com/javase/tutorial/essential/io/examples/Copy.java - what are the differences with yours ?Albertalberta
Mine just copies the files, theirs is a full app with copying of attributes.Milreis
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.Frumpish
S
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.

Silurian answered 2/6, 2011 at 13:0 Comment(2)
You probably can in Java, but it is like using a sledge-hammer to crack a walnut.Babble
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.Telestich
A
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();
            }
        }
    }
}
Allelomorph answered 6/10, 2014 at 10:49 Comment(5)
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.Mithras
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.Babbage
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!Opinicus
I think this is the clearer approach. What about with a progress bar ?Darbydarce
life saver I use it in kotlin WORKS PERFECT +2Conrado
M
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)
    }
}
Mithras answered 23/10, 2015 at 16:14 Comment(3)
How is this better than FileUtils.copyDirectory()?Arrowy
@Arrowy 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. :-)Mithras
You can replace FILES with groovy.io.FileType.FILES and DIRECTORIES with groovy.io.FileType.DIRECTORIES if you are wondering where those come from.Nathan
E
5
Extensometer answered 2/6, 2011 at 12:52 Comment(4)
Clarify "Java 7: take a look at java.nio.file.Files" - does not actually answer the questionAlbertalberta
While Files.copy supports directories, it does not copy the contents of the directories.Rotarian
apache is the best. +1Otherwise
@Otherwise Instead of "better" I'd say simpler.Hypotension
G
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();
        }

    }

}
Gelid answered 13/12, 2015 at 15:49 Comment(6)
why the downvote.. ? Please suggest if some improvement is desired.Gelid
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 eachCaoutchouc
Agreed, thankyou @CaoutchoucGelid
I would have suggested swapping out some boilerplate for lambdas but that will hurt people looking for Java 7 (6?) answers.Caoutchouc
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 ;)Caoutchouc
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.Caoutchouc
B
3

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

https://mcmap.net/q/138529/-how-to-copy-a-directory-with-its-attributes-permissions-from-one-location-to-another provides a complete JDK7 solution that does precisely that.

Breathed answered 9/9, 2013 at 5:28 Comment(1)
Please correct the link (the method is here : commons.apache.org/proper/commons-io/apidocs/org/apache/commons/…) but I guess you linked to the codeAlbertalberta
E
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

Excellence answered 2/6, 2011 at 12:56 Comment(1)
Files.copy does not support copying directory contents.Rotarian
B
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

Bellbella answered 15/12, 2014 at 20:34 Comment(1)
but how to add it to android project? where is dependency?Conrado

© 2022 - 2024 — McMap. All rights reserved.