[linux] rsync copy over only certain types of files using include option

I use the following bash script to copy only files of certain extension(in this case *.sh), however it still copies over all the files. what's wrong?

from=$1
to=$2

rsync -zarv  --include="*.sh" $from $to

This question is related to linux bash shell rsync

The answer is


Here's the important part from the man page:

As the list of files/directories to transfer is built, rsync checks each name to be transferred against the list of include/exclude patterns in turn, and the first matching pattern is acted on: if it is an exclude pattern, then that file is skipped; if it is an include pattern then that filename is not skipped; if no matching pattern is found, then the filename is not skipped.

To summarize:

  • Not matching any pattern means a file will be copied!
  • The algorithm quits once any pattern matches

Also, something ending with a slash is matching directories (like find -type d would).

Let's pull apart this answer from above.

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. Don't skip any directories
  2. Don't skip any .sh files
  3. Skip everything
  4. (Implicitly, don't skip anything, but the rule above prevents the default rule from ever happening.)

Finally, the --prune-empty-directories keeps the first rule from making empty directories all over the place.


One more addition: if you need to sync files by its extensions in one dir only (without of recursion) you should use a construction like this:

rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/

Pay your attention to the dot in the first --include. --no-r does not work in this construction.

EDIT:

Thanks to gbyte.co for the valuable comment!


If someone looks for this… I wanted to rsync only specific files and folders and managed to do it with this command: rsync --include-from=rsync-files

With rsync-files:

my-dir/
my-file.txt

- /*

Wrote this handy function and put in my bash scripts or ~/.bash_aliases. Tested sync'ing locally on Linux with bash and awk installed. It works

selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://stackoverflow.com/a/11111793/588867
# Example: selrsync 'tsv,csv' ./source ./target --dry-run
types="$1"; shift; #accepts comma separated list of types. Must be the first argument.
includes=$(echo $types| awk  -F',' \
    'BEGIN{OFS=" ";}
    {
    for (i = 1; i <= NF; i++ ) { if (length($i) > 0) $i="--include=*."$i; } print
    }')
restargs="$@"

echo Command: rsync -avz --prune-empty-dirs --include="*/" $includes --exclude="*" "$restargs"
eval rsync -avz --prune-empty-dirs --include="*/" "$includes" --exclude="*" $restargs
}

Avantages:

short handy and extensible when one wants to add more arguments (i.e. --dry-run).

Example:

selrsync 'tsv,csv' ./source ./target --dry-run

The answer by @chepner will copy all the sub-directories irrespective of the fact if it contains the file or not. If you need to exclude the sub-directories that dont contain the file and still retain the directory structure, use

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"

Examples related to linux

grep's at sign caught as whitespace How to prevent Google Colab from disconnecting? "E: Unable to locate package python-pip" on Ubuntu 18.04 How to upgrade Python version to 3.7? Install Qt on Ubuntu Get first line of a shell command's output Cannot connect to the Docker daemon at unix:/var/run/docker.sock. Is the docker daemon running? Run bash command on jenkins pipeline How to uninstall an older PHP version from centOS7 How to update-alternatives to Python 3 without breaking apt?

Examples related to bash

Comparing a variable with a string python not working when redirecting from bash script Zipping a file in bash fails How do I prevent Conda from activating the base environment by default? Get first line of a shell command's output Fixing a systemd service 203/EXEC failure (no such file or directory) /bin/sh: apt-get: not found VSCode Change Default Terminal Run bash command on jenkins pipeline How to check if the docker engine and a docker container are running? How to switch Python versions in Terminal?

Examples related to shell

Comparing a variable with a string python not working when redirecting from bash script Get first line of a shell command's output How to run shell script file using nodejs? Run bash command on jenkins pipeline Way to create multiline comments in Bash? How to do multiline shell script in Ansible How to check if a file exists in a shell script How to check if an environment variable exists and get its value? Curl to return http status code along with the response docker entrypoint running bash script gets "permission denied"

Examples related to rsync

Speed up rsync with Simultaneous/Concurrent File Transfers? How does `scp` differ from `rsync`? How to rsync only a specific list of files? rsync: difference between --size-only and --ignore-times rsync copy over only certain types of files using include option rsync - mkstemp failed: Permission denied (13) Using Rsync include and exclude options to include directory and file by pattern Copying files using rsync from remote server to local machine Why is this rsync connection unexpectedly closed on Windows? Copy or rsync command