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:

# 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?

  • I wonder why your attempt with touch didn't work. Is it the mv step or the touch step that changes the mtime of the subdirectories? What OS is on the NFS server, and (if you know) what filesystem type? – Gilles 'SO- stop being evil' Dec 10 '10 at 20:22
  • @Gilles: I do not know why is it happening. It is the mv step that causes trouble. The NFS server is actually a NetApp storage, I know virtually nothing about its internals. – Roman Zenka Dec 10 '10 at 22:15
  • 1
    Thanks. I suspect it's a NetApp oddity. Otherwise touch should have worked. By the way a more portable way would be touch -r "$1" reference.tmp; mv -- "$1" "$2"; touch -r reference.tmp -- "$2"; rm reference.tmp. – Gilles 'SO- stop being evil' Dec 10 '10 at 22:29
  • @Gilles: Very interesting, did not realize stat was not portable. – Roman Zenka Dec 11 '10 at 17:09

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.

| improve this answer | |
  • The mtime is more complicated than that. Only the parent directory and the directories directly under it have mtime changed. All other directories remain the same. One would expect either every single directory to be changed, or only the parent. – Roman Zenka Dec 9 '10 at 21:26
  • 1
    Actually, it makes sense: 1) The parent directory has the good mtime because it was explicitly set by touch, 2) The directory entries where recreated with the parent directory, but their mtime was not manually restored (Unix directory structure and inode format) 3) The rest of the tree structure wasn't actually changed, as we remained on the same volume : That's why mv has no "recursive" option, descending into subdirectories is only done if actual copy (different volumes, for example) is needed. – Eureka Dec 9 '10 at 21:51
  • @Eureka: Good explanation, but why is it done this way? If I was to implement mv on a directory data, I would simply change the .. in the data's contents and modify the source and target directories to list the moved item properly. No other directories would need to be touched. – Roman Zenka Dec 10 '10 at 5:51
  • 1
    @Roman Zenka After some search, this behaviour seems to be rather loosely specified between Unices and filesystems and to depend a lot of the underlying rename syscall implementation by the kernel and the used filesystem(s), NFS adding its share to the problem. There are some pointer referencing this kind of inconsistencies: patchwork.ozlabs.org/patch/25833 bugs.opensolaris.org/bugdatabase/… – Eureka Dec 10 '10 at 9:56
  • @Eureka: I find it extremely hard to believe that something I would consider so basic can be such a mess. It is almost 2011. Thanks for those resources! – Roman Zenka Dec 10 '10 at 16:35

Another solution may be:

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

| improve this answer | |
  • This does not seem to work on macOS. – Lenar Hoyt Sep 4 '17 at 22:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.