tar:添加当前目录中的所有文件和目录,包括.svn等
我尝试 tar.gz 目录并使用
tar -czf workspace.tar.gz *
生成的 tar 包含子目录中的 .svn 目录,但不在当前目录中(因为 *
扩展为仅“可见”文件在将其传递给 tar 之前,
我尝试使用
tar -czfworkspace.tar.gz .
来代替,但随后我收到错误,因为 '.' 在读取时已更改:
tar: ./workspace.tar.gz: file changed as we read it
是否有一个技巧可以使 *
匹配目录中的所有文件(包括点前缀)?
(在 Linux SLES-11 (2.6.27.19) 上使用 bash)
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(16)
不要在要打包的目录中创建 tar 文件:
确实可以,但解包时它会提取当前目录中的所有文件。更好的做法是:
或者,如果您不知道所在目录的名称:(
这假设您没有按照符号链接到达您所在的位置,并且 shell 不会尝试通过以下方式再次猜测您)通过符号链接向后跳转 -
bash
在这方面并不值得信赖,如果您必须担心这一点,请使用cd -P ..
进行物理更改目录。在我看来,这不是默认行为 - 至少对于那些cd ..
从来没有任何其他含义的人来说是令人困惑的。)讨论中的一条评论说:
注释的第一部分没有多大意义 - 如果 tar 文件包含当前目录,则当您从该存档中提取文件时不会创建它,因为根据定义,当前目录已经存在(除非在非常奇怪的情况下) )。
注释的第二部分可以通过以下两种方式之一处理:
/tmp
是一个可能的位置 - 然后将其移回原始位置完全的。--exclude=workspace.tar.gz
选项。=
后面的字符串是一个模式 - 该示例是最简单的模式 - 完全匹配。如果您在当前目录中工作而不符合建议,则可能需要指定--exclude=./workspace.tar.gz
;如果您按照建议升级一级,则可能需要指定--exclude=workspace/workspace.tar.gz
。如果您有多个要排除的 tar 文件,请使用“*
”,如--exclude=./*.gz
中。Don't create the tar file in the directory you are packing up:
does the trick, except it will extract the files all over the current directory when you unpack. Better to do:
or, if you don't know the name of the directory you were in:
(This assumes that you didn't follow symlinks to get to where you are and that the shell doesn't try to second guess you by jumping backwards through a symlink -
bash
is not trustworthy in this respect. If you have to worry about that, usecd -P ..
to do a physical change directory. Stupid that it is not the default behaviour in my view - confusing, at least, for those for whomcd ..
never had any alternative meaning.)One comment in the discussion says:
The first part of the comment does not make much sense - if the tar file contains the current directory, it won't be created when you extract file from that archive because, by definition, the current directory already exists (except in very weird circumstances).
The second part of the comment can be dealt with in one of two ways:
/tmp
is one possible location - and then move it back to the original location after it is complete.--exclude=workspace.tar.gz
option. The string after the=
is a pattern - the example is the simplest pattern - an exact match. You might need to specify--exclude=./workspace.tar.gz
if you are working in the current directory contrary to recommendations; you might need to specify--exclude=workspace/workspace.tar.gz
if you are working up one level as suggested. If you have multiple tar files to exclude, use '*
', as in--exclude=./*.gz
.需要执行几个步骤:
*
替换为.
以包含隐藏文件。--exclude=workspace.tar.gz
来排除存档本身。tar: .: filechanged as we read it
错误,请确保它存在(例如使用touch
),这样 --exclude 与存档文件名匹配。 (它与文件不存在不匹配)将其组合成以下脚本:
There are a couple of steps to take:
*
by.
to include hidden files as well.--exclude=workspace.tar.gz
can be used to exclude the archive itself.tar: .: file changed as we read it
error when the archive is not yet created, make sure it exists (e.g. usingtouch
), so the --exclude matches with the archive filename. (It does not match it the file does not exists)Combined this results in the following script:
如果您真的不想在压缩包中包含顶级目录(这通常是个坏主意):
If you really don't want to include top directory in the tarball (and that's generally bad idea):
在要压缩的目录(当前目录)中尝试以下操作:
in directory want to compress (current directory) try this :
您可以通过返回目录并执行以下操作来包含隐藏目录:
假设您想要 gzip 的目录称为工作区。
You can include the hidden directories by going back a directory and doing:
Assuming the directory you wanted to gzip was called workspace.
您可以使用
--exclude
修复.
表单:You can fix the
.
form by using--exclude
:还有另一种解决方案,假设文件夹中的项目数量并不大,并且假设所有名称都不包含 shell 解释为分隔符(空格)的字符:
(
ls -A
打印普通文件和隐藏文件,但不打印“.”和“..”就像ls -a
一样。)Yet another solution, assuming the number of items in the folder is not huge and assuming all names do not contain characters the shell interprets as delimiters (whitespace):
(
ls -A
prints normal and hidden files but not "." and ".." asls -a
does.)更新:我添加了对OP评论的修复。
确实会更改当前目录,但为什么不将文件放在其他地方呢?
Update: I added a fix for the OP's comment.
will indeed change the current directory, but why not place the file somewhere else?
实际上问题出在压缩选项上。技巧是将 tar 结果通过管道传输到压缩器,而不是使用内置选项。顺便说一句,这也可以为您提供更好的压缩,因为您可以设置额外的压缩选项。
最小焦油:
通过管道连接到您选择的压缩机。此示例很详细,并使用 xz 进行最大压缩:
解决方案已在 Windows 7 上的 Ubuntu 14.04 和 Cygwin 上进行了测试。
这是社区 wiki 的答案,因此如果您发现错误,请随时进行编辑。
Actually the problem is with the compression options. The trick is the pipe the tar result to a compressor instead of using the built-in options. Incidentally that can also give you better compression, since you can set extra compresion options.
Minimal tar:
Pipe to a compressor of your choice. This example is verbose and uses xz with maximum compression:
Solution was tested on Ubuntu 14.04 and Cygwin on Windows 7.
It's a community wiki answer, so feel free to edit if you spot a mistake.
我自己也有类似的情况。我认为最好在其他地方创建 tar,然后使用 -C 告诉 tar 压缩文件的基目录。示例:
这样就不需要排除您自己的 tar 文件。正如其他评论中所述,-A 将列出隐藏文件。
Had a similar situation myself. I think it is best to create the tar elsewhere and then use -C to tell tar the base directory for the compressed files. Example:
This way there is no need to exclude your own tarfile. As noted in other comments, -A will list hidden files.
这是个好问题。在 ZSH 中,您可以使用通配修饰符
(D)
,它代表“dotfiles”。比较:并且
这正确地排除了特殊目录条目
.
和..
。在 Bash 中,您可以使用.*
显式包含点文件:但这也包括
.
和..
,所以它不是您原来的样子寻找。我确信也有某种方法可以使*
匹配 bash 中的点文件。A good question. In ZSH you can use the globbing modifier
(D)
, which stands for "dotfiles". Compare:and
This correctly excludes the special directory entries
.
and..
. In Bash you can use.*
to include the dotfiles explicitly: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.这里提供的大多数解决方案的问题是 tar 在每个条目的开头都包含
./
。因此,当通过 GUI 压缩器打开它时,会产生.
目录。所以我最终做的是:ls -1A | xargs -d "\n" tar cfz my.tar.gz
如果当前目录中已有
my.tar.gz
,您可能需要将其 grep 出来:ls - 1A | grep -v my.tar.gz | grep -v my.tar.gz | xargs -d "\n" tar cfz my.tar.gz
请注意 xargs 有一定的限制(请参阅
xargs --show-limits
)。因此,如果您尝试创建一个包,该包在您尝试压缩的目录上包含大量条目(目录和文件),则此解决方案将不起作用。The problem with the most solutions provided here is that tar contains
./
at the begging of every entry. So this results in having.
directory when opening it through GUI compressor. So what I ended up doing is: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.10 年后,您有了
tar
的替代方案,如 Git 2.30(2021 年第一季度)所示,它使用“git 存档
"(man) 生成发布 tarball而不是 tar。
(您不需要 Git 2.30 来应用该替代方案)
请参阅 提交 4813277 (11 2020 年 10 月),以及提交 93e7031(2020 年 10 月 10 日) https://github.com/rscharfe" rel="nofollow noreferrer">René Scharfe (
rscharfe
)。(由 Junio C Hamano --
gitster
-- 合并于 提交 63e5273,2020 年 10 月 27 日)因此,而不是:
您只能使用 Git:
这最初是提议的,因为,如 此处解释,某些异国情调的平台可能有一个旧的 tar 发行版,缺少选项。
10 years later, you have an alternative to
tar
, illustrated with Git 2.30 (Q1 2021), which uses "git archive
"(man) to produce the release tarballinstead of tar.
(You don't need Git 2.30 to apply that alternative)
See commit 4813277 (11 Oct 2020), and commit 93e7031 (10 Oct 2020) by René Scharfe (
rscharfe
).(Merged by Junio C Hamano --
gitster
-- in commit 63e5273, 27 Oct 2020)So instead of:
You can do using Git only:
That was initially proposed because, as explained here, some exotic platform might have an old tar distribution with lacking options.
指定
.??*
将包含点后至少有 2 个字符的“点”文件和目录。缺点是它不会包含点后带有单个字符的文件/目录,例如.a
(如果有的话)。Specifying
.??*
will include "dot" files and directories that have at least 2 characters after the dot. The down side is it will not include files/directories with a single character after the dot, such as.a
, if there are any.使用
find
可能是最简单的方法:find 。 -maxdepth 1
将查找当前目录中的所有文件/目录/符号链接/等,并运行-exec
指定的命令。命令中的{}
表示文件列表位于此处,\+
表示该命令将运行为:而不是
Using
find
is probably the easiest way: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 file list goes here and\+
means that the command will be run as:instead of
如果磁盘空间不是问题,这也可能是一件非常容易做到的事情:
If disk space space is not an issue, this could also be a very easy thing to do: