关于linux:tar:添加当前目录INCLUDING .svn等所有文件和目录

tar: add all files and directories in current directory INCLUDING .svn and so on

我尝试tar.gz目录并使用

1
tar -czf workspace.tar.gz *

生成的tar包含子目录中的.svn目录,但不包含在当前目录中(因为*在传递到tar之前只扩展为"可见"文件

我试着

但是我收到了一个错误,因为''在阅读时发生了变化:

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

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

(在LinuxSLES-11(2.6.27.19)上使用bash)


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

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

执行此技巧,但在解包时它将提取当前目录中所有的文件。更好的做法是:

1
2
cd ..
tar -czf workspace.tar.gz workspace

或者,如果您不知道您所在目录的名称:

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

(这假设您没有按照symlinks来到达您所在的位置,并且shell不会试图通过symlink向后跳来猜测您,在这方面,bash是不可信的。如果您需要担心这个问题,可以使用cd -P ..来做物理更改目录。愚蠢的是,在我看来,这不是默认的行为——至少对于那些cd ..从来没有其他含义的人来说,这是令人困惑的。)

讨论中有一条评论说:

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

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

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

  • 或者:在其他地方创建文件-/tmp是一个可能的位置-然后在完成后将其移回原始位置。
  • 或者:如果您使用GNU TAR,请使用--exclude=workspace.tar.gz选项。=后面的字符串是一个模式——这个例子是最简单的模式——完全匹配。如果您在当前目录中工作与建议相反,则可能需要指定--exclude=./workspace.tar.gz;如果您按照建议向上工作一个级别,则可能需要指定--exclude=workspace/workspace.tar.gz。如果要排除多个tar文件,请使用"*",如--exclude=./*.gz中所示。

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

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


    要采取以下几个步骤:

  • .替换*以包含隐藏文件。
  • 要在同一目录中创建存档,可以使用--exclude=workspace.tar.gz排除存档本身。
  • 为了防止在尚未创建存档时出现tar: .: file changed as we read it错误,请确保它存在(例如,使用touch),因此--exclude与存档文件名匹配。(不匹配文件不存在)
  • 将此结果合并到以下脚本中:

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


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

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


    通过返回目录并执行以下操作,可以包括隐藏目录:

    1
    2
    cd ..
    tar -czf workspace.tar.gz workspace

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


    您可以使用--exclude修复.表单:

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


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

    最小焦油量:

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

    管道连接到压缩机。此示例是详细的,并使用具有最大压缩的XZ:

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

    该解决方案在Ubuntu 14.04和Cygwin的Windows7上进行了测试。这是一个社区wiki答案,所以如果你发现了错误,请随意编辑。


    更新:我为操作的评论添加了一个补丁。

    1
    tar -czf workspace.tar.gz .

    确实会更改当前目录,但为什么不将文件放在其他地方?

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


    一个好问题。在zsh中,可以使用globbing修饰符(D),它代表"点文件"。比较:

    1
    ls $HOME/*

    1
    ls $HOME/*(D)

    这正确地排除了...的特殊目录条目。在bash中,可以使用.*显式包含点文件:

    1
    ls $HOME/* $HOME/.*

    但这也包括...,所以这不是你想要的。我敢肯定,也有办法让*匹配bash中的点文件。


    我也有类似的情况。我认为最好在别处创建tar,然后使用-c告诉tar压缩文件的基本目录。例子:

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

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


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

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

    (ls -A打印正常和隐藏的文件,但不象ls -A那样打印"."和".."。)


    这里提供的大多数解决方案的问题是,tar在每一个条目的开头都包含./。因此,当通过GUI压缩器打开.目录时,会导致该目录。所以我最后做的是:

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

    如果您在当前目录中已经有my.tar.gz,您可能希望将其变为grep:

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

    注意xargs有一定的限制(见xargs --show-limits)。因此,如果您试图创建一个包,该包在您试图tar的目录中包含大量条目(目录和文件),那么该解决方案将不起作用。


    如果磁盘空间不是一个问题,这也可能是一件非常容易的事情:

    1
    2
    3
    mkdir backup
    cp -r ./* backup
    tar -zcvf backup.tar.gz ./backup

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

    指定.??*将包括点后至少有2个字符的"点"文件和目录。下面是它不包括点后有单个字符的文件/目录,如.a,如果有的话。


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

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

    find . -maxdepth 1将查找当前目录中的所有文件/目录/symlinks/etc,并运行-exec指定的命令。命令中的{}表示这里是文件列表,\+表示命令将以如下方式运行:

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

    而不是

    1
    2
    3
    tar zcvf workspace.tar.gz .file1
    tar zcvf workspace.tar.gz .file2
    tar zcvf workspace.tar.gz .dir3