排除特定文件/文件夹的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个回答

1402

你可以在tar命令中设置多个排除选项,例如:

$ tar --exclude='./folder' --exclude='./upload/folder2' -zcvf /backup/filename.tgz .

等等就可以了。确保在源和目标项目之前放置--exclude


101
这个答案让人以为 --exclude 应该放在第一位...tar cvfpz ../stuff.tgz --exclude='node_modules' --exclude='.git' . - James O'Brien
17
举个例子,如果您想备份WordPress项目文件夹但不包括uploads文件夹,则可以使用以下命令:tar -cvf wordpress_backup.tar wordpress --exclude=wp-content/uploads - shasi kanth
21
我想让你翻译以下命令:tar -zcv --exclude='file1' --exclude='patter*' --exclude='file2' -f /backup/filename.tgz . 请注意,-f 标志需要在 tar 文件之前。 参考:http://superuser.com/a/559341/415047 - Alfred Bez
27
在排除目录路径的末尾加上斜杠“/”会导致排除失败。我猜tar认为末尾的斜杠是要排除的目录名称的一部分。不好的写法:--exclude=mydir/ 好的写法:--exclude=mydir - Josiah
8
请在源文件和目标文件之前加上“--exclude”指令来排除指定的文件或文件夹。或者,您可以使用绝对路径来排除文件或文件夹:tar -cvpzf backups/target.tar.gz --exclude='/home/username/backups' /home/username - NightKnight on Cloudinsidr.com
显示剩余21条评论

157

你可以使用 --exclude 在 tar 命令中排除目录。

如果你想归档除了 /usr 目录之外的所有文件,可以使用以下命令:

tar -zcvf /all.tgz / --exclude=/usr

在您的情况下,可能需要类似于以下内容:

tar -zcvf archive.tgz arc_dir --exclude=dir/ignore_this_dir

22
可以使用完整路径来排除 (--exclude) 特定的内容。 - Johan Soderberg
9
有些情况下,在打包文件/文件夹之前需要使用“--exclude”排除它们。 - lobotmcj
1
请注意,--exclude=dir/ignore_this_dir 将在 任何 子树中匹配!你最终会错过一些意料之外被排除的文件。 - ygoe
1
在Ubuntu中,tar命令没有--exclude选项... 嗯 - wcochran

88

使用 tar 排除文件/目录备份的可能选项:

使用多个模式排除文件

tar -czf backup.tar.gz --exclude=PATTERN1 --exclude=PATTERN2 ... /path/to/backup

使用填有模式列表的排除文件来排除文件

tar -czf backup.tar.gz -X /path/to/exclude.txt /path/to/backup

通过在任何应该跳过的目录中放置一个标记文件,使用标记来排除文件

tar -czf backup.tar.gz --exclude-tag-all=exclude.tag /path/to/backup

4
参数的顺序似乎很重要,这种形式对我有效。 - cstamas
1
我也是。对于Ubuntu 16.04上的tar(GNU tar)1.28,只有这个特定的参数顺序才有效。 - arg

66

这个问题早已有很多答案,但我发现没有一个对我来说足够清晰明了,所以我想尝试自己的回答。

如果你有以下这种结构

/home/ftp/mysite/

带有以下文件/文件夹

/home/ftp/mysite/file1
/home/ftp/mysite/file2
/home/ftp/mysite/file3
/home/ftp/mysite/folder1
/home/ftp/mysite/folder2
/home/ftp/mysite/folder3

那么,您希望创建一个tar文件,其中包含/home/ftp/mysite内的所有内容(以便将网站移动到新服务器),但file3只是垃圾,folder3中的所有内容也都不需要,因此我们将跳过这两个。

我们使用的格式为

tar -czvf <name of tar file> <what to tar> <any excludes>

其中 c = 创建(create),z = 压缩(zip),v = 冗余模式(verbose,可以在添加文件时查看它们,有用的是为了确保排除的文件没有被添加)。并且 f = 文件(file)。

所以,我的命令看起来像这样

cd /home/ftp/
tar -czvf mysite.tar.gz mysite --exclude='file3' --exclude='folder3'

请注意,被排除的文件/文件夹是相对于您的tar根目录的(我已经尝试了相对于/的完整路径,但无法实现)。

希望这能帮助某人(也包括下次我谷歌时自己)


7
这个回答确实帮助了我!问题出在我的命令看起来像 tar -czvf mysite.tar.gz mysite --exclude='./mysite/file3' --exclude='./mysite/folder3',但这样并没有排除任何东西。 - Anish Ramaswamy
2
你的示例非常类似于我遇到的问题!谢谢! - Qorbani
3
很好,非常清晰,谢谢。对我来说问题在于其他答案包括绝对或相对路径。但你所要做的就是添加要排除的文件夹名称。 - Hubert
2
这是一个更清晰的答案。由于有示例,我能够让它正常工作,因为一开始路径很混乱。非常感谢! - fagiani
2
成功了!请记得不要在排除列表中添加尾部斜杠。例如,"file3" 或 "file3/subfolder" 是可以的,但是 "file3/" 和 "file3/subfolder/" 不行! - lucaferrario
显示剩余2条评论

45
您可以使用标准的“ant符号”来排除相对目录。
这对我很有效,可以排除任何.git或node_module目录:
tar -cvf myFile.tar --exclude=**/.git/* --exclude=**/node_modules/*  -T /data/txt/myInputFile.txt 2> /data/txt/myTarLogFile.txt

文件myInputFile.txt内容如下:

/dev2/java
/dev2/javascript


5
我认为这需要启用Bash shell选项变量globstar,可以使用命令shopt -s globstar来检查。我想在大多数基于Unix的操作系统上,默认情况下该选项是关闭的。根据Bash手册所述:“globstar: 如果设置了此选项,则在文件名扩展环境中使用的模式**将匹配所有文件、零个或多个目录和子目录。如果模式后面跟着一个'/',则只有目录和子目录会被匹配”。 - not2qubit
对我有用。我犯的错误是将 --exclude 放在源文件之后,一旦我将其放在源文件之前,它就可以正常工作了。 - Jose Quijada
在你所做的工作中,tar 本身有一个选项:--exclude-vcs。来自 tar(1) 的说明:“排除版本控制系统目录。” - mathway
2
这在我的MacOS上没有起作用,但是 --exclude=.git --exclude=node_modules 起了作用。我还不得不把 --exlcude 参数放在 tar 之后的第一个位置(即在 -c 之前)。我认为这是因为我使用了一些其他选项,但是我想留下这个提示以供其他人参考。 - Kip

27

这个排除模式处理文件名后缀,例如png或mp3,以及目录名称,如.git和node_modules。

tar --exclude={*.png,*.mp3,*.wav,.git,node_modules} -Jcf ${target_tarball}  ${source_dirname}

花括号的问题在于,它们可能会破坏你的Bash函数 :-) - PJ Brunet

19

我至少使用的是Cygwin版本的tar(“CYGWIN_NT-5.1 1.7.17(0.262 / 5/3)2012-10-19 14:39 i686 Cygwin”在Windows XP Home Edition SP3机器上),选项的顺序很重要。

虽然对我而言这种构造是有效的:

tar cfvz target.tgz --exclude='<dir1>' --exclude='<dir2>' target_dir

那个没有起作用:

tar cfvz --exclude='<dir1>' --exclude='<dir2>' target.tgz target_dir

这是,而tar --help则显示如下:

tar [OPTION...] [FILE]
所以,第二个命令应该也能起作用,但显然情况似乎并非如此...
敬礼,

6
仅想补充一点,重要的是要排除的目录末尾不应包含反斜杠。因此,--exclude='/path/to/exclude/dir' 是正确的,而--exclude='/path/to/exclude/dir/' 是错误的。 - GeertVc
21
这是因为目标存档文件target.tgz是f开关的参数,它应该跟在其后面。 - Valentino

19
阅读了各个版本的好答案并解决了我的问题后,我认为有些非常重要但很少在GNU/Linux通用使用中强调的细节,需要更多的关注而不仅仅是评论。
因此,我不会尝试回答每个情况下的问题,而是尝试记录查找位置,以便在出现问题时进行排查。 请注意:
  1. 选项的顺序很重要:在备份文件和目录之前或之后放置--exclude选项是不同的。这对我来说出人意料,因为在我的经验中,在GNU/Linux命令中,通常选项的顺序并不重要。
  2. 不同的tar版本期望以不同的顺序给出这些选项:例如,@Andrew's answer指出,在GNU tar v 1.26和1.28中,排除部分在最后,而在我的情况下,使用GNU tar 1.29,则相反。
  3. 结尾的斜杠很重要:至少在GNU tar 1.29中,不应该有结尾的斜杠。
在我的情况下,对于Debian stretch上的GNU tar 1.29,有效的命令如下:
tar --exclude="/home/user/.config/chromium" --exclude="/home/user/.cache" -cf file.tar  /dir1/ /home/ /dir3/

这些引号并不重要,它们可以有也可以没有。

我希望这对某人有用。


2
谢谢您的回答。我已经寻找(感觉很长时间)解决方案,而您的答案指引了我正确的方向。然而,在我的情况下(Ubuntu 18.04.3,Tar 1.29),我只能通过添加文件夹名称而不是路径来使其工作,例如:tar --exclude=folder1 --exclude=folder2 -czvf /opt/archieve.tgz folder - Nitai
我尝试了这个页面和tar版本1.27.1上的大多数选项,这个答案帮助了我。 - mattlangtree

18

我想展示另一种选项,以获取与之前提供的答案相同的结果。我有一个类似的情况,在那里我想将Android Studio项目一起备份到tar文件中上传到Media Fire。使用du命令查找大文件,我发现我不需要像build、linux和.dart_tools这样的某些目录。使用Charles_ma的第一个答案,我稍微修改了一下,以便能够从我的Android目录的父目录运行该命令。

tar --exclude='*/build' --exclude='*/linux' --exclude='*/.dart_tool' -zcvf androidProjects.tar Android/

它的效果非常好。

附注:如果这种回答不允许,请告知,我会删除。


17
如果你正在尝试排除版本控制系统(VCS)文件,tar 已经支持两个相关的选项!
1. 选项:--exclude-vcs 该选项可以排除以下版本控制系统使用的文件和目录:CVS,RCS,SCCS,SVN,Arch,Bazaar,Mercurial 和 Darcs。从版本 1.32 开始,将会排除以下文件:
- CVS/ 和其下所有内容 - RCS/ 和其下所有内容 - SCCS/ 和其下所有内容 - .git/ 和其下所有内容 - .gitignore - .gitmodules - .gitattributes - .cvsignore - .svn/ 和其下所有内容 - .arch-ids/ 和其下所有内容 - {arch}/ 和其下所有内容 - =RELEASE-ID - =meta-update - =update - .bzr - .bzrignore - .bzrtags - .hg - .hgignore - .hgrags - _darcs
2. 选项:--exclude-vcs-ignores

当归档一些处于某个版本控制系统(VCS)下的目录时,通常方便从该VCS的忽略文件(例如.cvsignore.gitignore等)读取排除模式。此选项提供了这样的可能性。

在归档一个目录之前,请查看它是否包含以下任意一个文件:cvsignore.gitignore.bzrignore.hgignore。如果有,则从这些文件中读取忽略模式。

这些模式会像相应的VCS一样进行处理,即:

.cvsignore

包含适用于此文件所在目录的 shell-style globbing 模式。文件中不允许有注释。空行将被忽略。

.gitignore

包含 shell-style globbing 模式。适用于包含 .gitfile 的目录及其所有子目录。

任何以 # 开头的行都是注释。反斜杠转义注释字符。

.bzrignore

包含 shell globbing 模式和正则表达式(如果以 RE:(16)为前缀)。模式影响目录及其所有子目录。

任何以 # 开头的行都是注释。

.hgignore

包含posix正则表达式(17)。行syntax:glob切换到shell globbing模式。行syntax:regexp切换回来。注释以#开头。模式影响目录及其所有子目录。

  1. 例子

tar -czv --exclude-vcs --exclude-vcs-ignores -f path/to/my-tar-file.tar.gz path/to/my/project/


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