I am trying to rsync only .bin files from folders beginning with 11.* and 14.* (including sub-folders), not older than 1 day.

What I have tried so far:

rsync -Rarv `find /mnt/IP/ftp/123/ -type f -mtime -1` --prune-empty-dirs --include "1[1][4]./" --include="*.bin" --exclude="*" "/mnt/IP/ftp/123/" "/home/ftp/123/"

It generally worked, but Rsync has created a directory with the same name inside of destination: /home/ftp/123/mnt/IP/ftp/123/

So I am looking for solution to re-create only folders beginning with 11.* or 14.*

  • The easy way out: find ... | grep ... | rsync -av --files-from=- /home/ftp/123 – Satō Katsura Feb 20 '17 at 17:04

This answer does not take the "not older than 1 day" restriction into account.

Rather than trying to parse the output of find, use rsync directly from find:

find /mnt/IP/ftp/123 -type -name '1[14].*' -prune \
    -exec rsync -av \
        --include='*.bin' --include='*/' \
        --exclude='*' --prune-empty-dirs {} /home/ftp/123 ';'

This would find the directories whose names start with either 11. or 14. in or under /mnt/IP/ftp/123. For each such directory, it would remove the directory from the search list (with -prune), and then execute

rsync -av --include='*.bin' --include='*/' \
    --exclude='*' --prune-empty-dirs {} /home/ftp/123 

where {} would be replaced by the pathname of the found directory.

The rsync command would create a subdirectory of /home/ftp/123 with the same filename as the found directory (i.e. starting with either 11. or 14.) and then copy the .bin files.

The inclusion and exclusion patterns used with rsync (first match wins):

  • --include='*.bin': include any file whose filename ends with .bin.
  • --include='*/': include any directory. Empty directories at the target will be removed due to --prune-empty-dirs.
  • --exclude='*': exclude anything not included by the previous rules.

You can use find to build the set of files that satisfy your three criteria:

  • Not older than one day
  • Must be in directories matching 11.* or 14.*
  • Files matching *.bin

and then feed that list to rsync for processing:

find mnt/IP/ftp/123/./ -mtime -1 \( -path '*/1[14].*/*' -prune \) -name '*.bin' -print0 |
    rsync -av --files-from - --from0 --prune-empty-dirs / dst/    

I've used -print0 and -from0 to ensure that files with unexpected characters in their names get processed correctly. The extra /./ in the find path is to indicate to rsync that everything before this component is to be stripped from the destination path. (If you decide to use a relative path in find (i.e. one that does not start with /) then change the rsync source from / to ..)

Example scenario

# All files in the example
find /mnt/IP/ftp/123/./ -type f

# Files matched by "find"
find mnt/IP/ftp/123/./ -mtime -1 \( -path '*/1[14].*/*' -prune \) -name '*.bin' -print

# Files copied by "rsync"
find /mnt/IP/ftp/123/./ -mtime -1 \( -path '*/1[14].*/*' -prune \) -name '*.bin' -print0 |
    rsync -av --files-from - --from0 --prune-empty-dirs / dst/
building file list ... done

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.