Tar: 添加工作目录中的所有文件和目录,包括. svn 等

我尝试 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上使用 bash (2.6.27.19)

305126 次浏览

You can include the hidden directories by going back a directory and doing:

cd ..
tar czf workspace.tar.gz workspace

假设您想要 gzip 的目录称为 workspace。

如果 真的不想在 tarball 中包含 top 目录(这通常是个坏主意) :

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

问得好。在 ZSH 中你可以使用 globbing 修饰符 (D),它代表“ dotfiles”。比较:

ls $HOME/*

and

ls $HOME/*(D)

这正确地排除了特殊目录条目 ...。在 Bash 中,可以使用 .*显式地包含 dotfiles:

ls $HOME/* $HOME/.*

But that includes . and .. as well, so it's not what you were looking for. I'm sure there's some way to make * match dotfiles in bash, too.

更新: 我为 OP 的注释添加了一个补丁。

tar -czf workspace.tar.gz .

的确会改变工作目录,但为什么不把文件放在别的地方呢?

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

你可以使用 --exclude修正 .表格:

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

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

不要在打包的目录中创建 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 ..没有任何其他含义的人来说,这是令人困惑的。)


讨论中的一条评论说:

I [...] need to exclude the top directory and I [...] need to place the tar in the base directory.

注释的第一部分没有多大意义——如果 tar 文件包含工作目录,那么当你从存档中提取文件时就不会创建它,因为根据定义,工作目录已经存在(除非在非常奇怪的情况下)。

评论的第二部分可以用以下两种方式之一处理:

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

Using find is probably the easiest way:

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

find . -maxdepth 1 will find all files/directories/symlinks/etc in the current directory and run the command specified by -exec. The {} in the command means 文件列表在这里 and \+ means that the command will be run as:

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

实际上问题在于压缩选项。技巧是将 tar 结果通过管道传递给压缩器,而不是使用内置选项。顺便说一下,这也可以提供更好的压缩,因为您可以设置额外的压缩选项。

最小焦油量:

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

管道到您选择的压缩器。这个例子很冗长,使用了最大压缩量的 xz:

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

解决方案在 Ubuntu 14.04上进行了测试,Cygwin 在 Windows 7上进行了测试。 It's a community wiki answer, so feel free to edit if you spot a mistake.

在目录中想要压缩(工作目录)试试这个:

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

如果磁盘空间不是问题,那么这也是一件非常容易做到的事情:

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

这里提供的大多数解决方案存在的问题是,tar 在每次进入时都包含 ./。因此,当通过 GUI 压缩器打开 .目录时,会产生这样的结果。所以我最后做的是:

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

If you already have my.tar.gz in current directory you may want to grep this out:

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

Be aware of that xargs has certain limit (see xargs --show-limits). So this solution would not work if you are trying to create a package which has lots of entries (directories and files) on a directory which you are trying to tar.

需要采取以下几个步骤:

  1. *替换为 .,以包含隐藏文件。
  2. To create the archive in the same directory a --exclude=workspace.tar.gz can be used to exclude the archive itself.
  3. 为了防止尚未创建归档文件时出现 tar: .: file changed as we read it错误,请确保存在(例如,使用 touch) ,以便 排除与归档文件名匹配。(它不匹配它的文件不存在)

结合这一点,产生了以下脚本:

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

还有另一种解决方案,假设文件夹中的项目数量不是很多,假设所有名称都不包含字符,shell 将其解释为分隔符(空格) :

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

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

我也有过类似的经历。我认为最好在其他地方创建 tar,然后使用-C 告诉 tar 压缩文件的基本目录。例如:

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

这样就不需要排除您自己的 tarfile。正如其他注释中指出的,-A 将列出隐藏文件。

10年后,您有了 tar的替代品,如 Git 2.30(Q12021)所示,它使用“ git archive(< a href = “ https://git-scm.com/docs/git-archive”rel = “ nofollow noReferrer”> man )来生成发行版 tarball 取而代之的是焦油。
(您不需要 Git 2.30来应用这个替代方案)

提交4813277(2020年10月11日)及 第93季,第7031集(2020年10月10日) by René Scharfe (rscharfe)
(由 朱尼奥 · C · 哈马诺 gitster合并于 commit 63e5273,2020年10月27日)

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

签名: René Scharfe

Reduce the dependency on external tools by generating the distribution archives for HTML documentation and manpages using git(< a href = “ https://git-scm.com/docs/git-”rel = “ nofollow noReferrer”> man ) commands instead of tar. 这为存档条目提供了与二进制文件的 dist 存档中相同的元数据。

所以不是:

tar cf ../archive.tar .

You can do using Git only:

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

这是最初提出的,因为作为 explained here,一些外来的平台可能有一个旧的焦油分布缺乏选择。