我尝试使用tar
备份我的文件。使用 时--exclude=/proc/
,存档包含 /proc 下的文件,而使用 时--exclude=/proc
则不包含。是什么导致了这种差异?
PS 我使用的shell是Bash。
答案1
对于目录而言,使用尾部斜杠与不使用尾部斜杠实际上没有太大区别,除了符号链接处理。请参阅开放群组基础规范,4.11 路径名解析(另见这个答案在 Unix SE 上)。
就 GNU tar 而言:--exclude
正如您所注意到的,模式中的尾部斜杠根本无法处理。如果有人要指出某事的话,这种差异只是由其特定的源代码造成的 :-)。请参阅这个问题在 Server Fault SE 上(尽管它没有提供太多细节 - 它只是陈述事实)。请参阅此邮件主题了解一些相关信息。在这段话中也许能找到一些线索(尽管我不太确定该如何理解):
Otto Moerbeek 写道:
这是一段代码是相关的:
/* * Some programs that create ustar archives append a '/' * to the pathname for directories. This clearly violates * ustar specs, but we will silently strip it off anyway. */ if (arcn-> name[arcn-> nlen - 1] == '/') arcn-> name[--arcn-> nlen] = '\0';
正如您使用 hexdump -C 查看 gtar 创建的档案时所看到的,gtar 就是这样一个程序。我不想仅仅为了适应不符合要求的程序而改变 tar。
答案2
通常,这取决于程序的惯例。对于 (GNU),tar
这有点不一致,因为尾随的 / 不会改变包括目录。该行为部分解释这里“模式和名称按原样使用“。Excludes 可以匹配名称的任何部分(除非您使用--anchor
)。
文档并未清楚说明其中是否存在差异,或者为什么存在差异。
从内部来看,排除中尾随的 / 不匹配的原因是tar
使用opendir(3)
,readdir(3)
和fnmatch(3)
--opendir()
接受/
目录尾随,readdir()
不在目录名称上加斜杠,并且fnmatch()
只匹配模式而不考虑现有文件或规范化。具体来说,fnmatch("proc/","proc",0)
返回 1(无匹配)。
比较一下rsync
目录名尾随 / 的区别,它们有非常明显(并且有据可查)的区别。
一个相关的问题是,有时你想备份一个目录,因为它是挂载点,尽管您不需要其内容。目的是让您的备份可以包含所有必需的挂载点 ( /dev
proc
/sys
),因此通常您需要执行以下操作:
tar --exclude=/proc/* --exclude=/sys/* --exclude=/dev/* [...]