Add convenience methods for copyToDirectory (closes closes
based on patch supplied by James Sawle
MODIFY
src/changes/changes.xml
src/changes/changes.xml
@@ -47,6 +47,9 @@ The <action> type attribute can be add,update,fix,remove.
<body>
<!-- The release date is the date RC is cut -->
<release version="2.6" date="2017-MM-DD" description="New features and bug fixes.">
+ <action issue="IO-367" dev="pschumacher" type="add" due-to="James Sawle">
+ Add convenience methods for copyToDirectory
+ </action>
<action issue="IO-442" dev="pschumacher" type="fix" due-to="Simon Robinson">
Javadoc contradictory for FileFilterUtils.ageFileFilter(cutoff) and the filter it constructs: AgeFileFilter(cutoff)
</action>

MODIFY
src/main/java/org/apache/commons/io/FileUtils.java
src/main/java/org/apache/commons/io/FileUtils.java
@@ -1531,6 +1531,75 @@ public static void copyToFile(final InputStream source, final File destination)
}
}
+ /**
+ * Copies a file or directory to within another directory preserving the file dates.
+ * <p>
+ * This method copies the source file or directory, along all its contents, to a
+ * directory of the same name in the specified destination directory.
+ * <p>
+ * 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.
+ * <p>
+ * <strong>Note:</strong> This method tries to preserve the files' last
+ * modified date/times using {@link File#setLastModified(long)}, however
+ * it is not guaranteed that those operations will succeed.
+ * If the modification operation fails, no indication is provided.
+ *
+ * @param src an existing file or directory to copy, must not be {@code null}
+ * @param destDir the directory to place the copy in, must not be {@code null}
+ *
+ * @throws NullPointerException if source or destination is {@code null}
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @see #copyDirectoryToDirectory(File, File)
+ * @see #copyFileToDirectory(File, File)
+ * @since 2.6
+ */
+ public static void copyToDirectory(final File src, final File destDir) throws IOException {
+ if (src == null) {
+ throw new NullPointerException("Source must not be null");
+ }
+ if (src.isFile()) {
+ copyFileToDirectory(src, destDir);
+ } else if (src.isDirectory()) {
+ copyDirectoryToDirectory(src, destDir);
+ } else {
+ throw new IOException("The source " + src + " does not exist");
+ }
+ }
+
+ /**
+ * Copies a files to a directory preserving each file's date.
+ * <p>
+ * This method copies the contents of the specified source files
+ * to a file of the same name in the specified destination directory.
+ * The destination directory is created if it does not exist.
+ * If the destination file exists, then this method will overwrite it.
+ * <p>
+ * <strong>Note:</strong> This method tries to preserve the file's last
+ * modified date/times using {@link File#setLastModified(long)}, however
+ * it is not guaranteed that the operation will succeed.
+ * If the modification operation fails, no indication is provided.
+ *
+ * @param srcs a existing files to copy, must not be {@code null}
+ * @param destDir the directory to place the copy in, must not be {@code null}
+ *
+ * @throws NullPointerException if source or destination is null
+ * @throws IOException if source or destination is invalid
+ * @throws IOException if an IO error occurs during copying
+ * @see #copyFileToDirectory(File, File)
+ * @since 2.6
+ */
+ public static void copyToDirectory(final Iterable<File> srcs, final File destDir) throws IOException {
+ if (srcs == null) {
+ throw new NullPointerException("Sources must not be null");
+ }
+ for (File src : srcs) {
+ copyFileToDirectory(src, destDir);
+ }
+ }
+
//-----------------------------------------------------------------------
/**
* Deletes a directory recursively.

MODIFY
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
@@ -1534,6 +1534,95 @@ public void testCopyDirectoryErrors() throws Exception {
}
}
+ // copyToDirectory
+
+ @Test
+ public void testCopyToDirectoryWithFile() throws IOException {
+ final File directory = new File(getTestDirectory(), "subdir");
+ if (!directory.exists()) {
+ directory.mkdirs();
+ }
+ final File destination = new File(directory, testFile1.getName());
+
+ FileUtils.copyToDirectory(testFile1, directory);
+ assertTrue("Check Exists", destination.exists());
+ assertEquals("Check Full Copy", testFile1Size, destination.length());
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testCopyToDirectoryWithFileSourceIsNull() throws IOException {
+ FileUtils.copyToDirectory((File) null, getTestDirectory());
+ }
+
+ @Test(expected=IOException.class)
+ public void testCopyToDirectoryWithFileSourceDoesNotExist() throws IOException {
+ FileUtils.copyToDirectory(new File(getTestDirectory(), "doesNotExists"), getTestDirectory());
+ }
+
+ @Test
+ public void testCopyToDirectoryWithDirectory() throws IOException {
+ final File destDirectory = new File(getTestDirectory(), "destination");
+ if (!destDirectory.exists()) {
+ destDirectory.mkdirs();
+ }
+
+ // Create a test directory
+ final File inputDirectory = new File(getTestDirectory(), "input");
+ if (!inputDirectory.exists()) {
+ inputDirectory.mkdirs();
+ }
+ final File outputDirDestination = new File(destDirectory, inputDirectory.getName());
+ FileUtils.copyToDirectory(testFile1, inputDirectory);
+ final File destFile1 = new File(outputDirDestination, testFile1.getName());
+ FileUtils.copyToDirectory(testFile2, inputDirectory);
+ final File destFile2 = new File(outputDirDestination, testFile2.getName());
+
+ FileUtils.copyToDirectory(inputDirectory, destDirectory);
+
+ // Check the directory was created
+ assertTrue("Check Exists", outputDirDestination.exists());
+ assertTrue("Check Directory", outputDirDestination.isDirectory());
+
+ // Check each file
+ assertTrue("Check Exists", destFile1.exists());
+ assertEquals("Check Full Copy", testFile1Size, destFile1.length());
+ assertTrue("Check Exists", destFile2.exists());
+ assertEquals("Check Full Copy", testFile2Size, destFile2.length());
+ }
+
+ @Test
+ public void testCopyToDirectoryWithIterable() throws IOException {
+ final File directory = new File(getTestDirectory(), "subdir");
+ if (!directory.exists()) {
+ directory.mkdirs();
+ }
+
+ List<File> input = new ArrayList<>();
+ input.add(testFile1);
+ input.add(testFile2);
+
+ final File destFile1 = new File(directory, testFile1.getName());
+ final File destFile2 = new File(directory, testFile2.getName());
+
+ FileUtils.copyToDirectory(input, directory);
+ // Check each file
+ assertTrue("Check Exists", destFile1.exists());
+ assertEquals("Check Full Copy", testFile1Size, destFile1.length());
+ assertTrue("Check Exists", destFile2.exists());
+ assertEquals("Check Full Copy", testFile2Size, destFile2.length());
+ }
+
+ @Test(expected=NullPointerException.class)
+ public void testCopyToDirectoryWithIterableSourceIsNull() throws IOException {
+ FileUtils.copyToDirectory((List<File>) null, getTestDirectory());
+ }
+
+ @Test(expected=IOException.class)
+ public void testCopyToDirectoryWithIterableSourceDoesNotExist() throws IOException {
+ FileUtils.copyToDirectory(Collections.singleton(new File(getTestDirectory(), "doesNotExists")),
+ getTestDirectory());
+ }
+
// forceDelete
@Test

IO-367: Add convenience methods for copyToDirectory (closes #34, closes #18)

based on patch supplied by James Sawle