5

So i'm trying to use the find command to find all files in my system with mtime -x. It does this but it does not "find" the directories of the file.

find . -mtime -2 -exec rsync -av {} /destination/ \;

I thought if i could bring over all the directories that it would feed into them if it could so i tried:

rsync -a -f"+ */" -f"- *" source/ destination/

Which works a charm for bringing over the directory tree but when i try to pull the files into it, they don't go into the separate directories, they just spill into the main directory i copied them into to.

Any ideas how i can get either the find command to find the directories too or another way around this problem?

6
  • Did you try rsync -avR instead of rsync -av? This should replicate the whole path on the destination.
    – Dubu
    Mar 11, 2014 at 12:22
  • @Dubu I just tried and it seems to copy the whole folder, regardless of mtime :o
    – user768352
    Mar 11, 2014 at 13:07
  • Hm. You should probably add -type f to your find command, so only files will be considered for transfer: find . -type f -mtime -2 -exec rsync -avR '{}' /destination/ \;
    – Dubu
    Mar 11, 2014 at 13:20
  • "So only files will be considered for transfer" - but i want directories transferred too, unless you mean i should run rsync -a -f"+ */" -f"- *" source/ dest/ before doing find . -type f -mtime -2 -exec rsync -avR '{}' /dest/ \; ?? @Dubu
    – user768352
    Mar 11, 2014 at 14:21
  • Nevermind! I tried it and it worked a treat! thanks. (do you wanna compile that into an answer and i'll mark it as sovled? or i can put it as an answer)
    – user768352
    Mar 11, 2014 at 14:22

1 Answer 1

7

There are two issues with this command line:

find . -mtime -2 -exec rsync -av {} /destination/ \;`

Transferring path names

First, when giving (single) file names to rsync and not simply a directory, it must be told explicitly to use the whole path and not only the filename for the destination. For this, use the option -R. From the manual page to rsync(1):

-R, --relative Use relative paths. This means that the full path names specified on the command line are sent to the server rather than just the last parts of the filenames. This is particularly useful when you want to send several different directories at the same time. For example, if you used this command: rsync -av /foo/bar/baz.c remote:/tmp/ ... this would create a file named baz.c in /tmp/ on the remote machine. If instead you used rsync -avR /foo/bar/baz.c remote:/tmp/ then a file named /tmp/foo/bar/baz.c would be created on the remote machine, preserving its full path. These extra path elements are called "implied directories" (i.e. the "foo" and the "foo/bar" directories in the above example). [...]

The manpage then continues on how to manipulate the path so that only parts of it will be present on the receiving side, but that is out of scope here.

Search for files only, not for directories

Second, find called as above will not only report files, but also directories. When a directory name is given to rsync as a source, it will synchronize that whole directory to the destination. This can be prevented using the additional test -type f ("type must be file") for find. Be aware, though, that this will not only exclude directories, but also sockets, named pipes, block and char devices, and symlinks. For symlinks, you could use the -xtype parameter instead, which will check the type of the symlink target.

Solution

So, the modified command line would look like this:

find . -type f -mtime -2 -exec rsync -av -R {} /destination/ \;

This will find all files (-type f) in the current path (.) that have been modified within the last two days (-mtime -2) and for each of them: execute (-exec) rsync, copying the file with the given name ({}) to /destination/, preserving most attributes (-a), giving verbose output (-v) and reproducing the whole path at the destination (-R).

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .