How to mv a folder in Linux retaining its mtime?

I am using CentOS 5.5 and would like to move a large amount of folders within one volume, retaining their mtime.

The best solution I could find is like this:

cp -p -r source/data target/
rm -rf source/data

With over 1TB of data on a NFS share, the copying takes forever. I do not want to copy. I want instantaneous move.

When I move a folder using mv source/data target/, the mtime of the folder (not the files) gets set to current time. This is because the contents of folder I am moving get modified by this operation (the .. entry is pointing to a different inode).

I came up with a following shell script I called mv_preserve_mtime.sh:

#!/bin/bash
# Moves source folder to target folder. 
# You are responsible for making sure the target does not exist, otherwise this blows up
export timestamp=`stat -c %y $1`
mv "$1" "$2"
touch --date="${timestamp}" $2

Well, that did not work either. The folder's mtime is restored, but all folders within the folder I move (only the ones 1 level deep) get their mtime reset for reasons I do not understand.

Does anyone have a proper, efficient and correct solution?


Solution 1:

POSIX mv doesn't provide any option to ask for atime/mtime preservation, but as the operation is local to a same volume, you can ask cp to use hard-links instead of copying data of the regular files using the -l option:

cp -p -r -l source/date target/
rm -rf source/data

Since only directories and file references will be actually copied, it should go much faster:

For more informations on hard-links, you can consult the corresponding Wikipedia page

As for why subdirectories mtime is being reset with your current solution, it's because you only get and restore the parent directory mtime : touch is not a recursive command.

Solution 2:

Another solution may be:

rsync -a --remove-source-files source/data target/