排除特定文件/文件夹的Shell命令来压缩目录

1094
有没有一种简单的shell命令/脚本可以排除某些文件/文件夹不被归档? 我有一个需要归档的目录,其中包含一个具有大量我不需要备份的非常大的文件的子目录。 用tar --exclude=PATTERN命令匹配给定的模式并排除那些文件,但我需要忽略特定的文件和文件夹(完整的文件路径),否则可能会排除有效的文件。我也可以使用find命令创建要排除的文件列表,并排除我不想存档的文件并将列表传递给tar,但这仅适用于少量文件。我有成千上万个文件。我开始认为唯一的解决方案是创建一个带有要排除的文件/文件夹列表的文件,然后使用rsync和--exclude-from = file将所有文件复制到tmp目录,然后再使用tar将该目录归档。有人能想到更好/更高效的解决方案吗? 编辑:Charles Ma的解决方案很好。 最大的问题在于--exclude='./folder'必须位于tar命令的开头。 完整命令(先CD,因此备份相对于该目录):
cd /folder_to_backup
tar --exclude='./folder' --exclude='./upload/folder2' -zcvf /backup/filename.tgz .

173
另外一件事让我困惑,或许值得注意的是:在被排除的文件夹路径后加上斜杠会导致tar根本无法排除这些文件夹。 - Rekhyt
7
@Rekhyt 感谢,我盯着这个命令看了15分钟...然后30分钟。 - earcam
12
看起来,--exclude 的位置取决于 tar 的版本。对于 tar 1.23 版本,--exclude 需要放在主命令之后。 - Joel G Mathew
3
别忘了使用“”(引号)。 - Meetai.com
7
“--exclude”不一定要放在第一个,但必须在源目录之前的某个位置(在Cygwin上测试过tar 1.29)。 - wortwart
显示剩余6条评论
31个回答

15

我在别处找到了这个解决方案,所以不会自己拍胸脯说是本人的功劳。但是对于我的Mac特定问题,它比上面所有的解决方案都要好(即使这个问题已经关闭):

tar zc --exclude __MACOSX --exclude .DS_Store -f <archive> <source(s)>

2
感谢您的回答,Darwin上的tar命令确实有不同的语法,其他答案中的“--exclude=blah”为什么不能工作一直让我很困惑。这在Mac上非常有效。 - Michael
1
使用tar时不要忘记加上COPYFILE_DISABLE=1,否则你的tar包里可能会有._文件 - Benoit Duffez
感谢您提供答案。包含您找到答案的来源链接总是很好的做法。奖励:如果来源是来自另一个stackoverflow或stackexchange帖子,您将获得额外的声望(积分或徽章 - 我不记得哪个了)。无论如何,他们会微笑,每个人都赢了。没有缺点 :-) 如果有人想搜索额外的信息,这也有助于人们。有时人们会因为您包含了源链接而点赞。最后,分享解决的具体问题或为什么这是更好的解决方案,可能会帮助其他遇到独特问题的人。 - SherylHohman

14

对于Mac OSX系统,我需要执行以下操作:

tar -zcv --exclude='文件夹名' -f 输出的压缩包名.tar 需要压缩的文件夹名

请注意在--exclude=之后加上-f参数。


13

对于那些遇到问题的人来说,一些 tar 版本在排除值中不使用 './' 才能正常工作。

Tar --version

tar(GNU tar)1.27.1

可用的命令语法:

tar -czvf ../allfiles-butsome.tar.gz * --exclude=acme/foo

这些不起作用:

$ tar -czvf ../allfiles-butsome.tar.gz * --exclude=./acme/foo
$ tar -czvf ../allfiles-butsome.tar.gz * --exclude='./acme/foo'
$ tar --exclude=./acme/foo -czvf ../allfiles-butsome.tar.gz *
$ tar --exclude='./acme/foo' -czvf ../allfiles-butsome.tar.gz *
$ tar -czvf ../allfiles-butsome.tar.gz * --exclude=/full/path/acme/foo
$ tar -czvf ../allfiles-butsome.tar.gz * --exclude='/full/path/acme/foo'
$ tar --exclude=/full/path/acme/foo -czvf ../allfiles-butsome.tar.gz *
$ tar --exclude='/full/path/acme/foo' -czvf ../allfiles-butsome.tar.gz *

10

我认为使用 --exclude 标志是正确的方法。

$ tar --exclude='./folder_or_file' --exclude='file_pattern' --exclude='fileA'

一个警告词语,有一个并不显然的副作用:在这个例子中排除文件A将会递归地搜索文件A!

例如:一个包含同名文件(data.txt)的单个子目录的目录。

data.txt
config.txt
--+dirA
  |  data.txt
  |  config.docx
  • 如果使用--exclude='data.txt',档案将都不包含 data.txt 文件。 如果要归档第三方库(例如 node_modules 目录),这可能会导致意外的结果。

  • 为避免这种情况,请确保给出完整路径,如--exclude='./dirA/data.txt'


7
阅读完这个帖子后,我在RHEL 5上进行了一些测试,以下是我压缩abc目录的结果:
这将排除error和logs目录以及目录下的所有文件:
tar cvpzf abc.tgz abc/ --exclude='abc/error' --exclude='abc/logs'

在排除的目录后添加通配符将排除文件但保留目录:
tar cvpzf abc.tgz abc/ --exclude='abc/error/*' --exclude='abc/logs/*'

在上面的第二个示例中,每个排除子句的最后一个斜杠后面应该有星号,但是帖子没有将它们包含进去。 - Mike

6
为避免在处理成千上万个文件时由于使用 find ... | xargs ... 而导致可能出现的 'xargs: Argument list too long' 错误,您可以将 find 的输出直接传输到 tar 中,使用命令 find ... -print0 | tar --null ...
# archive a given directory, but exclude various files & directories 
# specified by their full file paths
find "$(pwd -P)" -type d \( -path '/path/to/dir1' -or -path '/path/to/dir2' \) -prune \
   -or -not \( -path '/path/to/file1' -or -path '/path/to/file2' \) -print0 | 
   gnutar --null --no-recursion -czf archive.tar.gz --files-from -
   #bsdtar --null -n -czf archive.tar.gz -T -

你可以引用“exclude”字符串,例如'somedir/filesdir/*',那么shell不会展开星号和其他空格字符。 - Znik
xargs -n 1 是避免 xargs: Argument list too long 错误的另一种选项 ;) - Tuxdude

4

根据您的需求,您还可以使用以下"--exclude-tag"选项之一:

  • --exclude-tag=文件名
  • --exclude-tag-all=文件名
  • --exclude-tag-under=文件名

将排除指定文件所在的文件夹。


3
tar -cvzf destination_folder source_folder -X /home/folder/excludes.txt

-X表示一个文件,其中包含必须从备份中排除的文件名列表。例如,您可以在此文件中指定*〜,以不包括任何以〜结尾的文件名在备份中。


我认为这是最好的解决方案,因为它甚至可以在排除数量较多的情况下工作。还可以将X选项包含在选项包中,因此最短的形式可能是:tar cXvfJ EXCLUDE-LIST ARCHIVE.tar.xz SOURCE-FOLDER - Kai Petzke

3

gnu tar v 1.26版本中,--exclude命令需要紧随归档文件和备份目录参数之后,并且不应该包含前导或后缀斜杠,并且最好不要使用引号(单引号或双引号)。因此,相对于将要备份的PARENT目录,命令如下:

tar cvfz /path_to/mytar.tgz ./dir_to_backup --exclude=some_path/to_exclude


经过多次尝试,我发现在我的 tar (GNU tar) 1.28 命令中基本上是一样的。 - PicoutputCls

3
使用find命令和tar追加(-r)选项结合使用。这样,您可以在一个步骤中将文件添加到现有的tar文件中,而不是使用两个步骤的解决方案(创建文件列表,创建tar文件)。
find /dir/dir -prune ... -o etc etc.... -exec tar rvf ~/tarfile.tar {} \;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接