provide method overload for moveFile
added test cases
updated javadoc for "copy and delete" with setLastModified
MODIFY
src/main/java/org/apache/commons/io/FileUtils.java
src/main/java/org/apache/commons/io/FileUtils.java
@@ -2159,6 +2159,11 @@ public static void moveDirectoryToDirectory(final File src, final File destDir,
* <p>
* When the destination file is on another file system, do a "copy and delete".
* </p>
+ * <p>
+ * <strong>Note:</strong> This method tries to preserve the file's last modified date/times using
+ * {@link File#setLastModified(long)} when destination is another file system, however it is not guaranteed that the
+ * operation will succeed. If the modification operation fails, the methods throws IOException.
+ * </p>
*
* @param srcFile the file to be moved.
* @param destFile the destination file.
@@ -2169,12 +2174,39 @@ public static void moveDirectoryToDirectory(final File src, final File destDir,
* @since 1.4
*/
public static void moveFile(final File srcFile, final File destFile) throws IOException {
+ moveFile(srcFile, destFile, true);
+ }
+
+ /**
+ * Moves a file.
+ * <p>
+ * When the destination file is on another file system, do a "copy and delete".
+ * </p>
+ * <p>
+ * <strong>Note:</strong> Setting <code>preserveFileDate</code> to {@code true} tries to preserve the files' last
+ * modified date/times using {@link File#setLastModified(long)} when destination is another file system, however it
+ * is not guaranteed that those operations will succeed. If the modification operation fails, the methods throws
+ * IOException.
+ * </p>
+ *
+ * @param srcFile the file to be moved.
+ * @param destFile the destination file.
+ * @param preserveFileDate true if the file date of the "copy and delete" should be the same as the original when
+ * destination is on another file system. Param is not used if destination is on same file system.
+ * @throws NullPointerException if any of the given {@code File}s are {@code null}.
+ * @throws FileExistsException if the destination file exists.
+ * @throws IOException if source or destination is invalid.
+ * @throws IOException if an error occurs or setting the last-modified time didn't succeeded.
+ * @since 2.9.0
+ */
+ public static void moveFile(final File srcFile, final File destFile, final boolean preserveFileDate)
+ throws IOException {
validateMoveParameters(srcFile, destFile);
requireFile(srcFile, "srcFile");
requireAbsent(destFile, null);
final boolean rename = srcFile.renameTo(destFile);
if (!rename) {
- copyFile(srcFile, destFile);
+ copyFile(srcFile, destFile, preserveFileDate);
if (!srcFile.delete()) {
FileUtils.deleteQuietly(destFile);
throw new IOException("Failed to delete original file '" + srcFile +

MODIFY
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
src/test/java/org/apache/commons/io/FileUtilsTestCase.java
@@ -2165,6 +2165,67 @@ public boolean renameTo(final File f) {
assertTrue(!src.exists(), "Original deleted");
}
+ @Test
+ public void testMoveFile_CopyDelete_WithFileDatePreservation() throws Exception {
+ final File destination = new File(temporaryFolder, "move2.txt");
+
+ backDateFile10Minutes(testFile1); // set test file back 10 minutes
+
+ final File src = new File(testFile1.getAbsolutePath()) {
+ private static final long serialVersionUID = 1L;
+
+ // Force renameTo to fail, as if destination is on another
+ // filesystem
+ @Override
+ public boolean renameTo(final File f) {
+ return false;
+ }
+ };
+ final long expected = getLastModifiedMillis(testFile1);
+
+ FileUtils.moveFile(src, destination, true);
+ assertTrue(destination.exists(), "Check Exist");
+ assertTrue(!src.exists(), "Original deleted");
+
+ final long destLastMod = getLastModifiedMillis(destination);
+ final long delta = destLastMod - expected;
+ assertEquals(expected, destLastMod, "Check last modified date same as input, delta " + delta);
+ }
+
+ @Test
+ public void testMoveFile_CopyDelete_WithoutFileDatePreservation() throws Exception {
+ final File destination = new File(temporaryFolder, "move2.txt");
+
+ backDateFile10Minutes(testFile1); // set test file back 10 minutes
+
+ // destination file time should not be less than this (allowing for granularity)
+ final long now = System.currentTimeMillis() - 1000L;
+
+ final File src = new File(testFile1.getAbsolutePath()) {
+ private static final long serialVersionUID = 1L;
+
+ // Force renameTo to fail, as if destination is on another
+ // filesystem
+ @Override
+ public boolean renameTo(final File f) {
+ return false;
+ }
+ };
+ final long unexpected = getLastModifiedMillis(testFile1);
+
+ FileUtils.moveFile(src, destination, false);
+ assertTrue(destination.exists(), "Check Exist");
+ assertTrue(!src.exists(), "Original deleted");
+
+ // On Windows, the last modified time is copied by default.
+ if (!SystemUtils.IS_OS_WINDOWS) {
+ final long destLastMod = getLastModifiedMillis(destination);
+ final long delta = destLastMod - unexpected;
+ assertNotEquals(unexpected, destLastMod, "Check last modified date not same as input, delta " + delta);
+ assertTrue(destLastMod > now, destLastMod + " > " + now + " (delta " + delta + ")");
+ }
+ }
+
@Test
public void testMoveFile_CopyDelete_Failed() throws Exception {
final File destination = new File(temporaryFolder, "move3.txt");

IO-700: provide method overload for moveFile (#185)

- added test cases
- updated javadoc for "copy and delete" with setLastModified