Linux rsync 仅使用包含选项复制某些类型的文件

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/11111562/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-06 06:57:25  来源:igfitidea点击:

rsync copy over only certain types of files using include option

linuxbashshellrsync

提问by user881480

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?

我使用以下 bash 脚本仅复制特定扩展名的文件(在本例中为 *.sh),但它仍会复制所有文件。怎么了?

from=
to=

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

采纳答案by chepner

I think --includeis used to include a subset of files that are otherwise excluded by --exclude, rather than including only those files. In other words: you have to think about includemeaning don't exclude.

我认为--include用于包含由 排除的文件子集--exclude,而不是仅包含这些文件。换句话说:您必须考虑include 的含义不要 exclude

Try instead:

试试吧:

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

For rsync version 3.0.6 or higher, the order needs to be modified as follows (see comments):

对于rsync 3.0.6或更高版本,需要修改顺序如下(见评论):

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

Adding the -mflag will avoid creating empty directory structures in the destination. Tested in version 3.1.2.

添加-m标志将避免在目标中创建空目录结构。在 3.1.2 版本中测试。

So if we only want *.sh files we have to exclude all files --exclude="*", include all directories --include="*/"and include all *.sh files --include="*.sh".

因此,如果我们只想要 *.sh 文件,我们必须排除所有文件--exclude="*",包括所有目录--include="*/"并包括所有 *.sh 文件--include="*.sh"

You can find some good examples in the section Include/Exclude Pattern Rulesof the man page

你可以在手册页的包含/排除模式规则部分找到一些很好的例子

回答by Serge Roussak

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-rdoes not work in this construction.

注意第一个中的点--include--no-r在这个结构中不起作用。

EDIT:

编辑:

Thanks to gbyte.co for the valuable comment!

感谢 gbyte.co 的宝贵意见!

回答by WanderingMind

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

@chepner 的答案将复制所有子目录,而不管它是否包含文件。如果需要排除不包含该文件的子目录而仍保留目录结构,请使用

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

回答by Jim Hunziker

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.

随着要传输的文件/目录列表的构建,rsync 依次根据包含/排除模式列表检查要传输的每个名称,并对第一个匹配模式进行操作:如果它是排除模式,则该文件是跳过;如果是包含模式,则不会跳过该文件名;如果没有找到匹配的模式,则不会跳过文件名。

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 dwould).

此外,以斜杠结尾的内容是匹配目录(就像find -type d会)。

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 .shfiles
  3. Skip everything
  4. (Implicitly, don't skip anything, but the rule above prevents the default rule from ever happening.)
  1. 不要跳过任何目录
  2. 不要跳过任何.sh文件
  3. 跳过一切
  4. (隐含地,不要跳过任何内容,但上面的规则会阻止默认规则发生。)

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

最后,--prune-empty-directories第一个规则是避免在所有地方创建空目录。

回答by Pascal Polleunus

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

如果有人在寻找这个……我只想 rsync 特定的文件和文件夹,并设法使用以下命令来做到这一点: rsync --include-from=rsync-files

With rsync-files:

使用 rsync 文件:

my-dir/
my-file.txt

- /*

回答by biocyberman

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

编写了这个方便的函数并将其放入我的 bash 脚本或~/.bash_aliases. 使用 bash 在 Linux 上本地测试同步并awk安装。有用

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=""; 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).

当您想要添加更多参数(即--dry-run)时,方便且可扩展。

Example:

例子:

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