rsync根据.gitignore&.hgignore&svn排除:忽略像–filter =:C

Rsync包含一个漂亮的选项--cvs-exclude来“以与CVS相同的方式忽略文件”,但CVS已经过时了多年。 有没有办法让它排除现代版本控制系统(Git,Mercurial,Subversion)会忽略的文件?

例如,我有很多从GitHub签出的Maven项目。 通常他们包括一个.gitignore ,至less列出target ,默认的Maven构build目录(可能出现在顶层或子模块中)。 由于这些目录的内容完全是一次性的,而且可以远远大于源代码,所以在使用rsync进行备份时,我想排除它们。

当然,我可以明确地说--exclude=target/但是这会意外地压制那些恰好被命名为target并且不应该被忽略的不相关的目录。

我可以为我的磁盘上的任何.gitignore.hgignoresvn:ignore属性提供的所有文件名和模式的绝对path的完整列表,但这将是一个巨大的列表,必须由某种的脚本。

由于rsync没有内置的CVS以外的VCS检出支持,有没有什么好的方法可以把它们的忽略模式提供给它? 或者某种callback系统,用户脚本可以被询问是否应该包含给定的文件/目录?

更新 :– --filter=':- .gitignore'build议的--filter=':- .gitignore'似乎也适用于Git --filter=:C对于CVS至less在我已经find的例子上做了,尽pipe目前还不清楚语法是完全匹配的。 --filter=':- .hgignore'对Mercurial来说不是很好; 例如,一个包含像^target$ (Git /target/的Mercurial等价物)这样的行的.hgignore不能被rsync识别为正则expression式。 而且什么似乎都没有为Subversion工作,你将不得不parsing.svn/dir-prop-base为1.6或更早版本的工作副本,并为1.7或更高版本的工作副本惊慌失措。

正如luksan所提到的,你可以用--filter切换到rsync 。 我用--filter=':- .gitignore' (在“.gitignore”之前有一个空格)来实现这一点,它告诉rsync.gitignore文件进行目录合并,并且按照git的规则排除它们。 如果您有全局忽略文件,您可能还想添加您的全局忽略文件。 为了使它更容易使用,我创build了一个rsync的别名,其中包括filter。

rsync --exclude-from='path/.gitignore' --exclude-from='path/myignore.txt' source destination
它为我工作。
我相信你可以有更多的--exclude-from参数。

你可以使用git ls-files来build立被存储库的.gitignore文件排除的文件列表。 https://git-scm.com/docs/git-ls-files

选项:

  • --exclude-standard考虑所有.gitignore文件。
  • -o不要忽略未分离的更改。
  • -i只输出忽略的文件。
  • --directory如果整个目录被忽略,只输出目录path。

我唯一不理的就是.git

 rsync -azP --exclude=.git --exclude=`git -C <SRC> ls-files --exclude-standard -oi --directory` <SRC> <DEST> 

我有一些非常大的.gitignore文件,没有一个“纯粹的rsync”解决scheme为我工作。 我写了这个rsync包装器脚本 ,它完全尊重.gitignore规则(在子目录中包括!样式的exception和.gitignore文件),并为我工作的魅力。

为了mercurial,你可以使用

 hg status -i | sed 's/^I //' > /tmp/tmpfile.txt 

收集由于.hgignore限制而不属于mercurial控制的文件列表,然后运行

 rsync -avm --exclude-from=/tmp/tmpfile.txt --delete source_dir/ target_dir/ 

rsync除了忽略的所有文件。 注意rsync中的-m标志将排除空目录同步,因为hg status -i只会列出排除的文件,而不是dirs

查看rsync(1)中的MERGE-FILES FILTER RULES部分。

看起来可以创build一个rsync –filter规则,该规则将包含.gitignore文件作为遍历目录结构。

根据rsync手册页,除了文件模式的标准列表之外:

列在$ HOME / .cvsignore中的文件将被添加到列表以及CVSIGNORE环境variables中列出的任何文件

所以,我的$ HOME / .cvsignore文件如下所示:

 .git/ .sass-cache/ 

排除.git和Sass生成的文件。

您可以使用git ls-files来select每个rsync git ls-files ,而不是创build排除筛选器:

 #!/usr/bin/env bash if [[ ! $# -eq 2 ]] ; then echo "Usage: $(basename $0) <local source> <rsync destination>" exit 1 fi cd $1 versioned=$(git ls-files --exclude-standard) rsync --verbose --links --times --relative --protect-args ${versioned} $2 

这工作,即使git ls-files返回换行分隔的path。 如果您的文件名中包含空格的文件版本可能不会工作。