ChatGPT解决这个技术问题 Extra ChatGPT

Shell 命令到 tar 目录,不包括某些文件/文件夹

是否有一个简单的 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 .
另一件事引起了我的注意,可能值得注意:排除文件夹末尾的斜杠将导致 tar 根本不排除这些文件夹。
@Rekhyt 谢谢,我盯着命令看了 15 分钟……然后是 30
似乎 --exclude 的位置取决于 tar 的版本。对于 tar 1.23,--exclude 需要在主要命令之后。
不要忘记“'”(引号)。
--exclude 不必是第一个,但它必须位于源目录之前的某个位置(在 Cygwin 上使用 tar 1.29 进行了测试)。

e
ericosg

您可以为 tar 设置多个排除选项

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

等会工作。确保确保--exclude置于源和目标项之前。


这个答案使它看起来像 --exclude 首先... tar cvfpz ../stuff.tgz --exclude='node_modules' --exclude='.git' 。
例如,如果您尝试备份 wordpress 项目文件夹,不包括上传文件夹,您可以使用以下命令:tar -cvf wordpress_backup.tar wordpress --exclude=wp-content/uploads
我想出了以下命令:tar -zcv --exclude='file1' --exclude='patter*' --exclude='file2' -f /backup/filename.tgz . 注意 -f 标志需要在 tar 文件之前看到:superuser.com/a/559341/415047
排除目录末尾的“/”将导致它失败。我猜 tar 认为结尾 / 是要排除的目录名称的一部分。不好:--exclude=mydir/ 好:--exclude=mydir
> 确保将 --exclude 放在源项和目标项之前。或为排除使用绝对路径: tar -cvpzf backups/target.tar.gz --exclude='/home/username/backups' /home/username
f
fedorqui

您可以使用 --exclude 排除目录作为 tar。

如果您想归档除 /usr 之外的所有内容,您可以使用:

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

在你的情况下,也许像

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

为了澄清,您可以使用 --exclude 的完整路径。
在某些情况下,需要 --exclude 在要归档的文件/文件夹之前
请注意,--exclude=dir/ignore_this_dir 也会匹配 any 子树!您最终会丢失您没想到会被排除在外的文件。
S
Stephen Donecker

使用 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

参数的顺序似乎很重要,这种形式对我有用。
我也是。对于 Ubuntu 16.04 上的 tar (GNU tar) 1.28,只有这个特定的参数顺序有效。
S
Sverre

老问题有很多答案,但我发现没有一个对我来说足够清楚,所以我想添加我的尝试。

如果你有以下结构

/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

因此,您想制作一个包含 /home/ftp/mysite 中的所有内容的 tar 文件(以将站点移动到新服务器),但 file3 只是垃圾,也不需要 folder3 中的所有内容,所以我们将跳过这两个。

我们使用格式

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

其中 c = create、z = zip 和 v = verbose(您可以在输入文件时看到它们,这有助于确保没有添加您排除的文件)。和 f= 文件。

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

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

请注意,排除的文件/文件夹相对于您的 tar 的根目录(我在这里尝试了相对于 / 的完整路径,但我无法做到这一点)。

希望这会对某人有所帮助(以及我下次谷歌搜索时)


这个答案肯定对我有帮助!对我来说,问题是我的命令看起来像 tar -czvf mysite.tar.gz mysite --exclude='./mysite/file3' --exclude='./mysite/folder3',这并没有排除任何东西。
您的样本与我遇到的问题非常相似!谢谢!
很好,很清楚,谢谢。对我来说,问题是其他答案包括相对路径的绝对路径。但是您所要做的就是添加要排除的文件夹的名称。
这是一个更明确的答案。由于这个例子,我能够让它工作,因为路径起初令人困惑。非常感谢!
有效!请记住不要在排除项中添加尾部斜杠。例如,虽然“file3”或“file3/subfolder”有效,但“file3/”和“file3/subfolder/”无效!
R
Ronan Boiteau

您可以使用标准的“ant notation”来排除相对目录。这对我有用,不包括任何 .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


我相信这要求必须启用 Bash shell 选项变量 globstar。检查 shopt -s globstar。我认为它在大多数基于 unix 的操作系统上默认 关闭。来自 Bash 手册:“globstar: 如果设置,则在文件名扩展上下文中使用的模式 ** 将匹配所有文件以及零个或多个目录和子目录。如果模式后跟'/',只有目录和子目录匹配。"
S
Scott Stensland

此排除模式处理文件名后缀(如 png 或 mp3)以及目录名(如 .git 和 node_modules)

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

大括号的问题,它们可能会破坏你的 bash 函数:-)
G
GeertVc

我经历过这种情况,至少在我使用的 Cygwin 版本的 tar 中(“CYGWIN_NT-5.1 1.7.17(0.262/5/3) 2012-10-19 14:39 i686 Cygwin”在 Windows XP 家庭版上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]

所以,第二个命令也应该可以工作,但显然情况并非如此......

最好的rgds,


只是想补充一下,重要的是要排除的目录不应包含最后的反斜杠。所以,--exclude='/path/to/exclude/dir' 是正确的,--exclude='/path/to/exclude/dir/' 是错误的。
这是因为目标存档 target.tgz 是 f 开关的参数,它应该遵循
R
Rob

我在其他地方发现了这个,所以我不会相信,但对于我的 mac 特定问题,它比上述任何解决方案都更有效(即使它已关闭):

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

感谢您的回答,darwin 上的 tar 肯定有不同的语法,这让我发疯了,为什么其他答案中的“--exclude=blah”不起作用。这在 mac 上效果很好。
使用 tar 时不要忘记 COPYFILE_DISABLE=1,否则 you may get ._ files in your tarball
感谢您提供您的答案。包含指向您找到答案的来源的链接总是很好的。奖励:如果来源来自另一个 stackoverflow 或 stackexchange 帖子,您将获得额外的业力(积分或徽章 - 我不记得是哪个)。无论哪种方式,他们都会微笑,每个人都会赢。没有缺点:-) 如果想要搜索额外信息,它也可以帮助人们。有时人们会因为您包含源链接而投票。最后,分享这个解决的具体问题,或者为什么这是一个更好的解决方案,它可能会帮助其他有独特问题的人。
J
Jerinaw

对于 Mac OSX,我必须这样做

tar -zcv --exclude='folder' -f theOutputTarFile.tar folderToTar

注意 --exclude= 后面的 -f


u
user2553863

在阅读了不同版本的所有这些好的答案并为我自己解决了问题之后,我认为有非常小的细节非常重要,而且对于 GNU/Linux 的一般用途来说很少见,这些细节没有得到足够的重视,值得更多的评论。

因此,我不会尝试针对每种情况回答这个问题,而是尝试注册当事情不起作用时在哪里查看。

请务必注意:

选项的顺序很重要:将 --exclude 放在文件选项和要备份的目录之前与之后是不一样的。这至少对我来说是出乎意料的,因为根据我的经验,在 GNU/Linux 命令中,选项的顺序通常并不重要。不同的 tar 版本期望这个选项以不同的顺序:例如,@Andrew 的回答表明在 GNU tar v 1.26 和 1.28 中,排除项排在最后,而在我的情况下,对于 GNU tar 1.29,它是另一种方式。尾部斜线很重要:至少在 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/

引号无关紧要,无论有没有它们都有效。

我希望这对某人有用。


谢谢您的回答。我一直在寻找(感觉很长时间)一个解决方案,你的回答引导我朝着正确的方向前进。但是,就我而言(Ubuntu 18.04.3,Tar 1.29),我只能通过添加文件夹名称而不是路径来使其工作,例如:tar --exclude=folder1 --exclude=folder2 -czvf /opt/archieve。 tgz 文件夹
我在此页面和 tar 版本 1.27.1 上尝试了大多数选项,这个答案帮助了我。
T
T.M.

如果您尝试排除版本控制系统 (VCS) 文件,tar 已经支持两个有趣的选项! :)

选项:--exclude-vcs

此选项排除以下版本控制系统使用的文件和目录:CVSRCSSCCSSVNArchBazaarMercurialDarcs

从 1.32 版开始,以下文件被排除在外:

CVS/,以及它下面的一切

RCS/,以及它下面的一切

SCCS/,以及它下面的一切

.git/,以及它下面的所有内容

.gitignore

.gitmodules

.git 属性

.cvsignore

.svn/,以及它下面的一切

.arch-ids/,以及它下面的所有内容

{arch}/ 及其下的所有内容

=发布-ID

=元更新

=更新

.bzr

.bzrignore

.bzrtags

.hg

.hgignore

.hgrags

_darcs 选项:--exclude-vcs-ignores

选项:--exclude-vcs-ignores

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

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

这些模式的处理方式与相应的 VCS 处理它们的方式相同,即:

.cvsignore

包含仅适用于该文件所在目录的 shell 样式的通配模式。文件中不允许有评论。空行被忽略。

.gitignore

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

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

.bzrignore

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

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

.hgignore

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

例子

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


S
Samuel Liew

对于那些对此有疑问的人,某些版本的 tar 只有在排除值中没有 './' 的情况下才能正常工作。

Tar --version

焦油 (GNU 焦油) 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 *

R
Rck

我想展示另一个我用来获得与之前提供的答案相同的结果的选项,我有一个类似的情况,我想将 android studio 项目全部备份到一个 tar 文件中以上传到 media fire,使用 du 命令要查找大文件,我发现我不需要一些目录,例如: build, linux e .dart_tools 使用 Charles_ma 的第一个答案,我对其进行了一些修改,以便能够从 my 的父目录运行命令安卓目录。

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

它就像一个魅力。

附言。抱歉,如果不允许这种答案,如果是这种情况,我将删除。


A
Aaron Votre

我同意 --exclude 标志是正确的方法。

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

对于我没有立即发现的副作用的警告:在此示例中排除“fileA”将递归搜索“fileA”!

示例:具有单个子目录的目录,其中包含同名文件(data.txt)

data.txt
config.txt
--+dirA
  |  data.txt
  |  config.docx

如果使用 --exclude='data.txt' 存档将不包含任何 data.txt 文件。如果归档第三方库,例如 node_modules 目录,这可能会导致意外结果。

为避免此问题,请确保提供整个路径,例如 --exclude='./dirA/data.txt'


U
Undo

阅读此线程后,我在 RHEL 5 上做了一些测试,以下是我对 abc 目录进行 tar 处理的结果:

这将排除目录错误和日志以及目录下的所有文件:

tar cvpzf abc.tgz abc/ --exclude='abc/error' --exclude='abc/logs'

在排除目录后添加通配符将排除文件但保留目录:

tar cvpzf abc.tgz abc/ --exclude='abc/error/*' --exclude='abc/logs/*'

在上面的第二个示例中,每个 exclude 子句的最后一个斜杠后面应该有星号,但帖子没有使用它们。
c
carlo

为避免在处理数万个文件时由于使用 find ... | xargs ... 而可能出现的 'xargs: Argument list too long' 错误,您可以使用 find ... -print0 | tar --null ...find 的输出直接通过管道传送到 tar

# 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 不会扩展星号和其他白色字符。
xargs -n 1 是避免 xargs: Argument list too long 错误的另一种选择;)
f
frommelmak

您还可以根据需要使用“--exclude-tag”选项之一:

--排除标签=文件

--排除标记全部=文件

--exclude-tag-under=文件

将排除托管指定 FILE 的文件夹。


A
Alex B

将 find 命令与 tar append (-r) 选项结合使用。这样,您可以在一个步骤中将文件添加到现有的 tar,而不是通过两次解决方案(创建文件列表,创建 tar)。

find /dir/dir -prune ... -o etc etc.... -exec tar rvf ~/tarfile.tar {} \;

c
camh

您可以使用 cpio(1) 创建 tar 文件。 cpio 将文件归档到标准输入,因此,如果您已经确定了要用于选择归档文件的 find 命令,请将其通过管道传输到 cpio 以创建 tar 文件:

find ... | cpio -o -H ustar | gzip -c > archive.tar.gz

A
Andrew

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 中的命令大致相同。
A
Ashwini Gupta
tar -cvzf destination_folder source_folder -X /home/folder/excludes.txt

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


我认为,这是最好的解决方案,因为它甚至在那些情况下也有效,排除的数量很大。也可以在选项包中包含 X 选项,因此最短的形式可能是:tar cXvfJ EXCLUDE-LIST ARCHIVE.tar.xz SOURCE-FOLDER
R
RohitPorwal

一探究竟

tar cvpzf zip_folder.tgz . --exclude=./public --exclude=./tmp --exclude=./log --exclude=fileName

S
Sridhar Kumar N

成功案例: 1)如果给全路径做备份,在exclude中也应该使用全路径。

tar -zcvf /opt/ABC/BKP_27032020/backup_27032020.tar.gz --exclude='/opt/ABC/csv/' --exclude='/opt/ABC/log/' /opt/ABC

2) 如果给当前路径做备份,在排除中也应该只使用当前路径。

tar -zcvf backup_27032020.tar.gz --exclude='ABC/csv/' --exclude='ABC/log/' ABC

失败案例:

如果给当前路径目录进行备份并忽略完整路径,则无法使用 tar -zcvf /opt/ABC/BKP_27032020/backup_27032020.tar.gz --exclude='/opt/ABC/csv/' --exclude='/ opt/ABC/log/' ABC

注意:在备份目录之前/之后提及排除是可以的。


J
Joe

最好的办法是通过 xargs 将 find 与 tar 一起使用(处理大量参数)。例如:

find / -print0 | xargs -0 tar cjf tarfile.tar.bz2

这可能会导致 tar 被多次调用 - 并且还会重复打包文件。正确的是:find / -print0 | tar -T- --null --no-recursive -cjf tarfile.tar.bz2
我在某处读到,当使用 xargs 时,应该使用 tar r 选项而不是 c,因为当 find 实际找到大量结果时,xargs 将拆分这些结果(基于本地命令行参数限制)成块并在每个部分上调用 tar 。这将生成一个包含 xargs 返回的最后一个块的存档,而不是 find 命令找到的所有结果。
G
George

可能多余的答案,但因为我发现它很有用,这里是:

虽然是 FreeBSD 根目录(即使用 csh),但我想将整个根文件系统复制到 /mnt 但没有 /usr 和(显然)/mnt。这是有效的(我在/):

tar --exclude ./usr --exclude ./mnt --create --file - . (cd /mnt && tar xvd -)

我的全部观点是,有必要(通过放置 ./)指定 tar 排除的目录,其中较大目录的一部分被复制。

我的 €0.02


C
Community

我没有运气让 tar 排除几个级别深的 5 GB 子目录。最后,我只是使用了 unix Zip 命令。它对我来说更容易。

因此,对于原始帖子中的这个特定示例(tar --exclude='./folder' --exclude='./upload/folder2' -zcvf /backup/filename.tgz 。)

相当于:

zip -r /备份/文件名.zip。 -x 上传/文件夹/**\* 上传/文件夹2/**\*

(注意:这是我最初使用的对我有帮助的帖子 https://superuser.com/questions/312301/unix-zip-directory-but-excluded-specific-subdirectories-and-everything-within-t


注意:zip 不会打包空目录,但 tar 会!
d
dobrivoje

我想在本地主机上有新的前端版本(角度文件夹)。另外,在我的情况下, git 文件夹很大,我想排除它。我需要从服务器下载它,然后解压它才能运行应用程序。

从 /var/lib/tomcat7/webapps 压缩 angular 文件夹,将其移动到名称为 angular.23.12.19.tar.gz 的 /tmp 文件夹

命令 :

tar --exclude='.git' -zcvf /tmp/angular.23.12.19.tar.gz /var/lib/tomcat7/webapps/angular/

E
ESP32

似乎不可能排除具有绝对路径的目录。一旦任何路径是绝对的(源或/和排除),排除命令将不起作用。这是我尝试了所有可能的组合后的经验。


C
Community

以下 bash 脚本应该可以解决问题。它使用 Marcus Sundman 给出的答案 here

#!/bin/bash

echo -n "Please enter the name of the tar file you wish to create with out extension "
read nam

echo -n "Please enter the path to the directories to tar "
read pathin

echo tar -czvf $nam.tar.gz
excludes=`find $pathin -iname "*.CC" -exec echo "--exclude \'{}\'" \;|xargs`
echo $pathin

echo tar -czvf $nam.tar.gz $excludes $pathin

这将打印出您需要的命令,您可以将其复制并粘贴回去。可能有一种更优雅的方式可以将其直接提供给命令行。

只需将 *.CC 更改为您想要排除的任何其他常见扩展名、文件名或正则表达式,这应该仍然有效。

编辑

只是添加一点解释; find 生成与所选正则表达式匹配的文件列表(在本例中为 *.CC)。该列表通过 xargs 传递给 echo 命令。这将打印 --exclude '列表中的一个条目'。斜杠 () 是 ' 标记的转义字符。


对于大多数 shell 脚本来说,要求交互式输入是一个糟糕的设计选择。改为读取命令行参数,您将受益于 shell 的选项卡完成、历史完成、历史编辑等。
此外,您的脚本不适用于包含空格或 shell 元字符的路径。您应该基本上总是将变量放在双引号中,除非您特别要求 shell 执行空格标记化和通配符扩展。详情请参阅stackoverflow.com/questions/10067266/…