tar:将所有文件和目录添加到当前目录中,包括.svn等


89

我尝试在tar.gz目录中使用

tar -czf workspace.tar.gz *

生成的tar包含.svn子目录中的目录,但不包含当前目录中的目录(因为*在传递给tar之前已扩展为仅“可见”文件

我尝试过了

tar -czf workspace.tar.gz .相反,但是然后我得到一个错误,因为“。” 阅读时发生了变化:

tar: ./workspace.tar.gz: file changed as we read it

有没有技巧可以*匹配目录中的所有文件(包括点缀)?

(在Linux SLES-11(2.6.27.19)上使用bash


5
也许这个问题属于超级用户?
Peter Jaric 2010年

Answers:


75

不要在要打包的目录中创建tar文件:

tar -czf /tmp/workspace.tar.gz .

可以做到这一点,除了在您解压缩时会在当前目录中提取所有文件。最好做:

cd ..
tar -czf workspace.tar.gz workspace

或者,如果您不知道所在目录的名称,请执行以下操作:

base=$(basename $PWD)
cd ..
tar -czf $base.tar.gz $base

(这是假设您没有遵循符号链接来到达您所在的位置,并且shell不会尝试通过符号链接向后跳来猜测您的情况-bash在这方面是不可信的。如果您为此担心,用于cd -P ..创建物理更改目录。愚蠢的是,这不是我认为的默认行为-至少对于那些cd ..从来没有其他含义的人来说是一个困惑。)


讨论中的一则评论说:

我需要排除顶层目录,而我需要将tar放在基本目录中。

注释的第一部分意义不大-如果tar文件包含当前目录,则从该归档文件中提取文件时将不会创建该注释,因为根据定义,当前目录已经存在(在非常奇怪的情况下除外) )。

注释的第二部分可以通过以下两种方式之一处理:

  1. 要么:在其他/tmp位置创建文件-可能是一个位置-完成后将其移回原始位置。
  2. 或者:如果您使用的是GNU Tar,请使用该--exclude=workspace.tar.gz选项。后面的字符串=是一个模式-该示例是最简单的模式-完全匹配。您可能需要指定--exclude=./workspace.tar.gz是否在当前目录中工作,这与建议相反;您可能需要指定--exclude=workspace/workspace.tar.gz您是否正在按照建议进行一级操作。如果要排除多个tar文件,请使用“ *”,如中所示--exclude=./*.gz

1
好的答案,但是我不得不在必须打包的目录中运行此命令。我没有足够的权限在外部运行它。
Hexodus 2014年

当然,一个完美的打包地点是/ tmp。
Andre Fellows

45

如果您真的不想在压缩包中包含顶层目录(那通常是个坏主意):

tar czf workspace.tar.gz -C /path/to/workspace .

我需要排除顶层目录,并且需要将tar放在基本目录中。
Micha 2010年

@Micha做一个bash脚本来归档和文件复制后
Fedir RYKHTIK

2
我想您在-czf中缺少-。
2014年

10
man tar:tar的第一个参数应该是一个函数;字母Acdrtux之一或长函数名称之一。 功能字母不必以前缀-,也可以与其他单字母选项结合使用。
rkhayrov 2014年

4
仍然不起作用,我仍然有“。” 作为我的tarball中的顶级目录
A. Gille

43

可以采取几个步骤:

  1. 替换*.包括隐藏的文件。
  2. 在同一目录中创建档案 --exclude=workspace.tar.gz可以使用排除档案本身。
  3. 为了防止在tar: .: file changed as we read it尚未创建存档时出现错误,请确保它存在(例如,使用touch),因此--exclude与存档文件名匹配。(与之不匹配的文件不存在)

结合使用以下脚本可得出以下结果:

touch workspace.tar.gz
tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

7
我阅读了所有答案和评论,这是在同一目录中创建tarball的最好方法。从这个答案中,我也理解了为什么会发生此错误。
SzymonSadło17年

如果要在压缩tar文件时查看进度,可以为添加一个附加标志--verbose,例如: -czvf
Mastrianni

18

在要压缩的目录中(当前目录)尝试以下操作:

tar -czf workspace.tar.gz . --exclude=./*.gz

2
但是现在它抱怨文件“。” 被读取时更改。我可以确定所有文件都包含在内吗?
2015年

1
这将排除.gz目录中的所有文件。
omerfarukdogan

12

您可以通过返回目录并执行以下操作来包含隐藏目录:

cd ..
tar czf workspace.tar.gz workspace

假设您要gzip的目录称为工作区。


并且这也避免了更改文件的问题。
乔纳森·莱夫勒

当用户在父文件夹中没有写权限时,该功能将不起作用。
Joachim Wagner

就是@JoachimWagner!
p01ymath

1
@JoachimWagner。如果您没有写许可,请将其更改为:tar -czf /path/to/where/you/do/have/permission/workspace.tar.gz workspace
bramp

1
我必须先取出-才能czf使它工作。否则,我会收到Cannot stat: No such file or directory错误消息。
Phemelo Khetho,

6

您可以.使用--exclude以下方法来修复表单:

tar -czf workspace.tar.gz --exclude=workspace.tar.gz .

5

更新:我为OP的评论添加了一个修复程序。

tar -czf workspace.tar.gz .

确实会更改当前目录,但是为什么不将文件放在其他位置呢?

tar -czf somewhereelse/workspace.tar.gz .
mv somewhereelse/workspace.tar.gz . # Update

该文件将在之后进行处理,并且必须位于工作区中-这有点丑陋,但只是需要使用(整个过程只是一种解决方法...)
Micha 2010年

OK,我将为此添加一个修复程序:)
Peter Jaric 2010年

并且,如果您需要能够重复运行此命令,请在tar行之前添加“ rm Workspace.tar.gz”。
Peter Jaric 2010年

如果您想将整个驱动器放到同一驱动器中,似乎没有太多选择。
BeeOnRope

4

实际上,问题在于压缩选项。诀窍是将焦油结果输送到压缩器,而不是使用内置选项。顺便说一句,由于可以设置额外的压缩选项,因此还可以为您提供更好的压缩效果。

最小焦油:

tar --exclude=*.tar* -cf workspace.tar .

用管道输送到您选择的压缩机。这个例子很冗长,并使用具有最大压缩率的xz:

tar --exclude=*.tar* -cv . | xz -9v >workspace.tar.xz

解决方案已在Ubuntu 14.04和Windows 7上的Cygwin上进行了测试。这是社区Wiki的答案,因此,如果发现错误,请随时进行编辑。


谢谢!拯救生命
史蒂文

2

这里提供的大多数解决方案的问题在于./,每次输入的开头都会包含tar 。因此.,通过GUI压缩程序打开目录时会导致具有目录。所以我最终要做的是:

ls -1A | xargs -d "\n" tar cfz my.tar.gz

如果您已经my.tar.gz在当前目录中,则可能需要grep出来:

ls -1A | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz

请注意,xargs具有一定的限制(请参阅参考资料xargs --show-limits)。因此,如果您尝试创建一个在目录中包含很多条目(目录和文件)的程序包,则该解决方案将不起作用。


1

一个好问题。在ZSH中,您可以使用globlob修饰符(D),它表示“ dotfiles”。相比:

ls $HOME/*

ls $HOME/*(D)

这将正确排除特殊目录条目...。在Bash中,您可以用来.*显式包含点文件:

ls $HOME/* $HOME/.*

但是,包括...为好,所以它不是你所期待的。我敢肯定,也有一些方法可以*在bash中创建匹配的点文件。


在bash中,用于.??*匹配所有的点文件not...。不会得到单字符点文件(如.a)。要获得同样的效果,请使用更复​​杂的.[^.]*
Scott Minster 2013年

1

假设文件夹中的项目数量不多,则是另一种解决方案:

tar -czf workspace.tar.gz `ls -A`

ls -A打印普通文件和隐藏文件,但不打印“。”和“ ..” ls -a。)


0
tar -czf workspace.tar.gz .??* *

指定.??*将包括点之后至少包含2个字符的“点”文件和目录。不利的一面是,它将不包括点后带有单个字符的文件/目录,例如.a,如果有的话。


0

如果磁盘空间空间不是问题,那么做起来也很容易:

mkdir backup
cp -r ./* backup
tar -zcvf backup.tar.gz ./backup

0

我自己也有类似情况。我认为最好在其他位置创建tar,然后使用-C告诉tar压缩文件的基本目录。例:

tar -cjf workspace.tar.gz -C <path_to_workspace> $(ls -A <path_to_workspace>)

这样就无需排除自己的tarfile。如其他注释所述,-A将列出隐藏文件。


0

10年后,您有了tarGit 2.30(Q1 2021)的替代品,它使用“ git archiveman来生产发行版tarball 而不是tar。
(您不需要Git 2.30即可应用该替代方法)

提交4813277(2020年10月11日),以及提交93e7031(2020年10月10日)由勒Scharfe( )rscharfe
(由Junio C gitsterHamano合并--commit 63e5273中,2020年10月27日)

Makefile:使用git init / add / commit / archive for dist-doc

签字人:RenéScharfe

通过使用man命令而不是tar生成HTML文档和联机帮助页的发行档案来减少对外部工具的依赖。这为存档条目提供了与dist存档二进制文件相同的元数据。git

所以代替:

tar cf ../archive.tar .

您只能使用Git:

git -C workspace init
git -C workspace add .
git -C workspace commit -m workspace
git -C workspace archive --format=tar --prefix=./ HEAD^{tree} > workspace.tar
rm -Rf workspace/.git

最初提出该建议是因为,如此处所述,某些奇特的平台可能具有较旧的tar发行版,缺少选项。


-1

使用find可能是最简单的方法:

find . -maxdepth 1 -exec tar zcvf workspace.tar.gz {} \+

find . -maxdepth 1将在当前目录中找到所有文件/目录/符号链接/ etc,并运行由指定的命令-exec。该{}命令中的表示文件列表位于此处\+表示该命令将以以下方式运行:

tar zcvf workspace.tar.gz .file1 .file2 .dir3

代替

tar zcvf workspace.tar.gz .file1
tar zcvf workspace.tar.gz .file2
tar zcvf workspace.tar.gz .dir3

-J在手册中是--xz;与-c组合只是计算机将其称为“乐趣”的开始:)
Ricalsin

哈哈,我在家中的小型服务器受磁盘空间的限制比受CPU的限制更大。我将其更改为使用gzip。
安德鲁·甘纳森
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.