我使用以下bash脚本仅复制特定扩展名的文件(在此示例中为*.sh),但它仍会复制所有文件。有什么问题吗?
from=$1 to=$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"
。
您可以在 man 页面的Include/Exclude Pattern Rules 部分找到一些好的示例。
rsync -zarv --include="*/" --include="*.sh" --exclude="*" "$from" "$to"
。 - Bijou Trouvaille--include=\*.sh
,然后再使用--exclude=\*
)。 - TrueY@chepner的答案将复制所有子目录,无论其中是否包含文件。如果您需要排除不包含该文件的子目录,并仍保留目录结构,请使用
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
--include "*/"
感到好奇 - rsync 手册中的过滤规则说,“第一个匹配的模式会被执行”,所以我不明白为什么如果我们只使用第二个包含模式 (--include="*.sh"
),这个命令就不能正常工作 - 难道这不是第一个匹配并执行我们想要的文件的模式吗? - David Streid这是 man 手册中的重要部分:
当构建文件/目录传输列表时,rsync 会逐个检查要传输的名称与包含/排除模式列表匹配情况,第一个匹配的模式将被执行:如果它是一个排除模式,则跳过该文件;如果它是一个包含模式,则不跳过该文件名;如果没有匹配的模式,则不跳过该文件名。
总结一下:
同时,以斜杠结尾的内容是匹配目录的(就像 find -type d
命令一样)。
让我们分析以上回答。
rsync -zarv --prune-empty-dirs --include "*/" --include="*.sh" --exclude="*" "$from" "$to"
.sh
文件最后,--prune-empty-directories
避免第一条规则在各个地方创建空目录。
--include "*/"
不应该允许同步任何目录中的任何文件吗?或者匹配文件是否需要同时匹配目录模式和文件模式? - FlexMcMurphy*
匹配任何路径组件,但会在斜杠处停止。" - Jim Hunziker另外要补充的一点是:如果你需要在仅一个目录中按其扩展名同步文件(不进行递归),则应该使用以下结构:
rsync -auzv --include './' --include '*.ext' --exclude '*' /source/dir/ /destination/dir/
请注意第一个--include
中的点号。在这种情况下,--no-r
无效。
编辑:
感谢gbyte.co的宝贵评论!
编辑:
-uzv
标志与此问题无直接关系,但我通常会使用它们。
include
和exclude
选项的顺序是按照它们在命令中出现的顺序。此外,它会在第一个匹配到的选项处停止。因此,在这个例子中,如果我们在第一位指定了--exclude '*'
,rsync将不会执行任何操作。请参阅手册以获取更多解释。 - Serge Roussak--include '*.ext'
而不是 --include '.ext'
。 - gbyte我编写了这个方便的函数,并将其放在我的bash脚本或~/.bash_aliases
中。在安装有bash和awk
的Linux本地测试同步,它能够正常工作。
selrsync(){
# selective rsync to sync only certain filetypes;
# based on: https://dev59.com/Dmgu5IYBdhLWcg3wv5ca#11111793
# 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 --include-from=rsync-files
使用 rsync-files:my-dir/
my-file.txt
- /*
rsync
吗?这完全可以通过shell内部实现。 - Inian