草庐IT

linux - Golang 压缩目录

coder 2023-07-01 原文

我无法弄清楚如何将目录写入 tarball 的 headerinfo。例如,我有这个目录结构:

test [dir]
-- test1.txt
    -- subDirA [sub dir]
         -- test2.txt

如果我使用我的 Go tar 可执行文件对测试进行压缩,它将解压缩并具有原始结构。如果我在 tarball 上执行 tar -tvf,列表将是:

test/test1.txt 
test/subDirA/test2.txt

但是,如果我手动执行 tar -cvf 测试,然后执行 tar -tvf,列表将是:

test/
test/test1.txt
test/subDirA/
test/subDirA/test2.txt

这也是我希望我的 Go tarring 程序做的。在我的 Go 程序中,我尝试添加一个新方法 writeDirToTar 来处理将目录添加到 tarWriter 中。我从 fileWalk 函数调用 writeFileToTar 或 writeDirToTar。当我在 writeDirToTar 中调用 io.Copy(tarWriter, file) 时,出现“test/subDirA is a directory”错误,这是有道理的。有解决办法吗?

func writeToTar(fileDir string,
        sourceBase string,
        tarWriter *tar.Writer,
        f os.FileInfo) error {

        file, err := os.Open(fileDir)
        if err != nil {
                log.Print("error opening file")
                return err
        }
        defer file.Close()

        // relative paths are used to preserve the directory paths in each file path
        relativePath, err := filepath.Rel(sourceBase, fileDir)

        tarheader := new(tar.Header)
        tarheader.Name = relativePath
        tarheader.Size = f.Size()
        tarheader.Mode = int64(f.Mode())
        tarheader.ModTime = f.ModTime()

        err = tarWriter.WriteHeader(tarheader)
        if err != nil {
                log.Print("error writing tarHeader")
                return err
        }
        _, err = io.Copy(tarWriter, file)
        if err != nil {
                log.Print("error writing to tarWriter")
                return err
        }
        return nil
}

func writeDirToTar(fileDir string,
        sourceBase string,
        tarWriter *tar.Writer,
        f os.FileInfo) error {

        file, err := os.Open(fileDir)
        if err != nil {
                log.Print("error opening file")
                return err
        }
        defer file.Close()

        // relative paths are used to preserve the directory paths in each file path
        relativePath, err := filepath.Rel(sourceBase, fileDir)

        if tarHeader, err := tar.FileInfoHeader(f, relativePath); err != nil {
                log.Print("error writing tarHeader")
                return err
        }

        tarHeader.Name = relativePath
        tarheader.Mode = int64(f.Mode())
        tarheader.ModTime = f.ModTime()

        _, err = io.Copy(tarWriter, file)
        if err != nil {
                log.Print("error writing to tarWriter")
                return err
        }
        return nil

}

最佳答案

您缺少 tar.Header 中的 Typeflag 字段。

对于您至少需要的目录:

tarheader := &tar.Header{
    Name:     relativePath,
    Mode:     int64(f.Mode()),
    ModTime:  f.ModTime(),
    Typeflag: tar.TypeDir,
}

这里不需要大小,也不需要复制目录数据,因为内部目录数据结构对 tar 没有任何意义。

您可能还想在文件名中添加 / 以直观地指示它是一个目录并匹配 POSIX tar 行为。

或者你可以只使用 tar.FileInfoHeader功能就像您对文件所做的那样,以创建正确的标题结构。

关于linux - Golang 压缩目录,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39646584/

有关linux - Golang 压缩目录的更多相关文章

  1. ruby - 使用 RubyZip 生成 ZIP 文件时设置压缩级别 - 2

    我有一个Ruby程序,它使用rubyzip压缩XML文件的目录树。gem。我的问题是文件开始变得很重,我想提高压缩级别,因为压缩时间不是问题。我在rubyzipdocumentation中找不到一种为创建的ZIP文件指定压缩级别的方法。有人知道如何更改此设置吗?是否有另一个允许指定压缩级别的Ruby库? 最佳答案 这是我通过查看ruby​​zip内部创建的代码。level=Zlib::BEST_COMPRESSIONZip::ZipOutputStream.open(zip_file)do|zip|Dir.glob("**/*")d

  2. ruby-on-rails - active_admin 目录中的常量警告重新声明 - 2

    我正在使用active_admin,我在Rails3应用程序的应用程序中有一个目录管理,其中包含模型和页面的声明。时不时地我也有一个类,当那个类有一个常量时,就像这样:classFooBAR="bar"end然后,我在每个必须在我的Rails应用程序中重新加载一些代码的请求中收到此警告:/Users/pupeno/helloworld/app/admin/billing.rb:12:warning:alreadyinitializedconstantBAR知道发生了什么以及如何避免这些警告吗? 最佳答案 在纯Ruby中:classA

  3. ruby-on-rails - 如何在 Gem 中获取 Rails 应用程序的根目录 - 2

    是否可以在应用程序中包含的gem代码中知道应用程序的Rails文件系统根目录?这是gem来源的示例:moduleMyGemdefself.included(base)putsRails.root#returnnilendendActionController::Base.send:include,MyGem谢谢,抱歉我的英语不好 最佳答案 我发现解决类似问题的解决方案是使用railtie初始化程序包含我的模块。所以,在你的/lib/mygem/railtie.rbmoduleMyGemclassRailtie使用此代码,您的模块将在

  4. ruby-on-rails - 没有这样的文件或目录 - 用 Mini Magick 识别 - 2

    在我让另一个人重做我的前端UI之前,我的Rails应用程序运行平稳。我已经尝试解决此错误3天了。这是错误:Nosuchfileordirectory-identifyExtractedsource(aroundline#59):575859606162@post=Post.find(params[:id])authorize@postif@post.update_attributes(post_params)flash[:notice]="Postwasupdated."redirect_to[@topic,@post]else{"utf8"=>"✓","_method"=>"patc

  5. ruby - Ruby 的压缩库? - 2

    是否有任何可用于Ruby的开源压缩/解压库?有没有人实现过LZW?或者,是否有任何使用压缩组件的开源库可以提取出来独立使用?编辑——感谢您的回答!我应该提到我必须压缩的是只驻留在数据库中的长字符串(我不会压缩文件)。此外,如果可以执行此操作的任何库都具有用于客户端压缩/分解的等效JavaScript实现,那将是理想的,因为这将用于Web应用程序。 最佳答案 您会在rubystdlib下找到所有已交付的ruby​​库的一个很好的列表.我会使用zlib库,它是开放的,无处不在,您会发现几乎所有语言的库!

  6. ruby - Sinatra 找不到 View 目录 - 2

    我正在尝试以一种更类似于普通RubyGem结构的方式构建我的Sinatra应用程序。我有以下文件树:.├──app.rb├──config.ru├──Gemfile├──Gemfile.lock├──helpers│  ├──dbconfig.rb│  ├──functions.rb│  └──init.rb├──hidden│  └──Rakefile├──lib│  ├──admin.rb│  ├──api.rb│  ├──indexer.rb│  ├──init.rb│  └──magnet.rb├──models│  ├──init.rb│  ├──invite.rb│  ├─

  7. ruby - 如何在 ruby​​ 中复制目录结构,不包括某些文件扩展名 - 2

    我想编写一个ruby​​脚本来递归复制目录结构,但排除某些文件类型。因此,给定以下目录结构:folder1folder2file1.txtfile2.txtfile3.csfile4.htmlfolder2folder3file4.dll我想复制这个结构,但不包含.txt和.cs文件。因此,生成的目录结构应如下所示:folder1folder2file4.htmlfolder2folder3file4.dll 最佳答案 您可以使用查找模块。这是一个代码片段:require"find"ignored_extensions=[".cs"

  8. ruby-on-rails - 在 Rails 中需要整个目录树的好方法是什么? - 2

    我正在使用Rails3.2.2并希望递归加载某个目录中的所有代码。例如:[Railsroot]/lib/my_lib/my_lib.rb[Railsroot]/lib/my_lib/subdir/support_file_00.rb[Railsroot]/lib/my_lib/subdir/support_file_01.rb...基于谷歌搜索,我试过:config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**"]config.autoload_paths+=["#{Rails.root.to_s}/lib/my_lib/**/"

  9. ruby - 使用 File.open 从 ruby​​ 中的目录打开文件 - 2

    我是Ruby的新手,我正在尝试以如下方式打开文件:#!/usr/bin/envrubydata_file='~/path/to/file.txt'file=File.open(data_file,'r')但是我得到“没有这样的文件或目录”(该文件确实存在于该目录中)。如果我将该文件路径作为命令行参数,它会起作用,例如:#!/usr/bin/envrubyfile=File.open(ARGV[0],'r')然后从命令行运行,如:rubyscript.cgi~/path/to/file.txt关于如何让它以第一种方式工作的任何想法? 最佳答案

  10. ruby - 在 Ruby + Chef 中检查现有目录失败 - 2

    这是我在ChefRecipe中的一blockRuby:#ifdatadirdoesn'texist,moveoverthedefaultoneif!File.exist?("/vol/postgres/data")execute"mv/var/lib/postgresql/9.1/main/vol/postgres/data"end结果是:Executingmv/var/lib/postgresql/9.1/main/vol/postgres/datamv:inter-devicemovefailed:`/var/lib/postgresql/9.1/main'to`/vol/post

随机推荐