153

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

从=$1
到=$2

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

6 回答 6

262

我认为--include用于包含以其他方式排除的文件子集--exclude,而不是仅包含那些文件。换句话说:您必须考虑包含含义不排除

请尝试:

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

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

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

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

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

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

于 2012-06-20T01:48:42.093 回答
75

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

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
于 2015-09-11T15:42:29.830 回答
30

这是手册页中的重要部分:

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

总结一下:

  • 不匹配任何模式意味着将复制文件!
  • 一旦任何模式匹配,算法就会退出

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

让我们从上面拆开这个答案。

rsync -zarv  --prune-empty-dirs --include "*/"  --include="*.sh" --exclude="*" "$from" "$to"
  1. 不要跳过任何目录
  2. 不要跳过任何.sh文件
  3. 跳过所有内容
  4. (隐含地,不要跳过任何内容,但上面的规则会阻止默认规则发生。)

最后,--prune-empty-directories保持第一条规则不会在整个地方创建空目录。

于 2018-07-23T13:55:03.183 回答
19

另一个补充:如果您只需要在一个目录中通过其扩展名同步文件(没有递归),您应该使用这样的结构:

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

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

编辑:

感谢 gbyte.co 的宝贵意见!

编辑:

这些-uzv标志与这个问题没有直接关系,但我将它们包括在内,因为我经常使用它们。

于 2014-02-17T13:32:16.010 回答
3

编写了这个方便的函数并放入我的 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="$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
}

好处:

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

例子:

selrsync 'tsv,csv' ./source ./target --dry-run
于 2020-04-20T09:49:15.267 回答
0

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

使用 rsync 文件:

my-dir/
my-file.txt

- /*
于 2020-04-11T19:39:46.623 回答