我使用以下 bash 脚本仅复制特定扩展名的文件(在本例中为 *.sh),但它仍然复制所有文件。怎么了?
从=$1 到=$2 rsync -zarv --include="*.sh" $from $to
我认为--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"
。
您可以在手册页的包含/排除模式规则部分找到一些很好的示例
@chepner 的答案将复制所有子目录,无论它是否包含文件。如果您需要排除不包含文件的子目录并仍保留目录结构,请使用
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
这是手册页中的重要部分:
随着要传输的文件/目录列表的建立,rsync 会依次检查要传输的每个名称与包含/排除模式列表的比较,并且对第一个匹配模式进行操作:如果它是排除模式,则该文件是跳过;如果它是包含模式,则不会跳过该文件名;如果没有找到匹配的模式,则不跳过文件名。
总结一下:
此外,以斜杠结尾的内容是匹配目录(就像find -type d
会一样)。
让我们从上面拆开这个答案。
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
.sh
文件最后,--prune-empty-directories
保持第一条规则不会在整个地方创建空目录。
另一个补充:如果您只需要在一个目录中通过其扩展名同步文件(没有递归),您应该使用这样的结构:
rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/
请注意第一个中的点--include
。--no-r
在这种结构中不起作用。
编辑:
感谢 gbyte.co 的宝贵意见!
编辑:
这些-uzv
标志与这个问题没有直接关系,但我将它们包括在内,因为我经常使用它们。
编写了这个方便的函数并放入我的 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
如果有人在寻找这个……我只想 rsync 特定的文件和文件夹,并设法用这个命令来做到这一点:rsync --include-from=rsync-files
使用 rsync 文件:
my-dir/
my-file.txt
- /*