How to get desired path for the files inside tar while tarring them up

huangapple go评论153阅读模式
英文:

How to get desired path for the files inside tar while tarring them up

问题

我一直在使用这段代码来写入一个tar文件。我像这样调用它:err = retarIt(dirTopDebug, path),其中dirTopDebug是我的tar文件的路径(/tmp/abc.tar),path是我想要添加的文件的路径(/tmp/xyz/...)。当我解压生成的tar文件时,我发现文件被放在/tmp/xyz/..的格式中。但是我希望它们在tar文件中的位置是xyz/...,即没有tmp文件夹。

我该如何做到这一点?

  1. func TarGzWrite(_path string, tw *tar.Writer, fi os.FileInfo) {
  2. fr, _ := os.Open(_path)
  3. //handleError(err)
  4. defer fr.Close()
  5. h := new(tar.Header)
  6. h.Name = _path
  7. h.Size = fi.Size()
  8. h.Mode = int64(fi.Mode())
  9. h.ModTime = fi.ModTime()
  10. err := tw.WriteHeader(h)
  11. if err != nil {
  12. panic(err)
  13. }
  14. _, _ = io.Copy(tw, fr)
  15. //handleError( err )
  16. }
  17. func IterDirectory(dirPath string, tw *tar.Writer) {
  18. dir, _ := os.Open(dirPath)
  19. //handleError( err )
  20. defer dir.Close()
  21. fis, _ := dir.Readdir(0)
  22. //handleError( err )
  23. for _, fi := range fis {
  24. fmt.Println(dirPath)
  25. curPath := dirPath + "/" + fi.Name()
  26. if fi.IsDir() {
  27. //TarGzWrite( curPath, tw, fi )
  28. IterDirectory(curPath, tw)
  29. } else {
  30. fmt.Printf("adding... %s\n", curPath)
  31. TarGzWrite(curPath, tw, fi)
  32. }
  33. }
  34. }
  35. func retarIt(outFilePath, inPath string) error {
  36. fw, err := os.Create(outFilePath)
  37. if err != nil {
  38. return err
  39. }
  40. defer fw.Close()
  41. gw := gzip.NewWriter(fw)
  42. defer gw.Close()
  43. // tar write
  44. tw := tar.NewWriter(gw)
  45. defer tw.Close()
  46. IterDirectory(inPath, tw)
  47. fmt.Println("tar.gz ok")
  48. return nil
  49. }

以上是你提供的代码。要将文件放在tar文件中的xyz/...位置,而不是/tmp/xyz/..,你可以在TarGzWrite函数中修改h.Name的值。将h.Name设置为fi.Name()即可。修改后的代码如下:

  1. func TarGzWrite(_path string, tw *tar.Writer, fi os.FileInfo) {
  2. fr, _ := os.Open(_path)
  3. //handleError(err)
  4. defer fr.Close()
  5. h := new(tar.Header)
  6. h.Name = fi.Name() // 修改这里
  7. h.Size = fi.Size()
  8. h.Mode = int64(fi.Mode())
  9. h.ModTime = fi.ModTime()
  10. err := tw.WriteHeader(h)
  11. if err != nil {
  12. panic(err)
  13. }
  14. _, _ = io.Copy(tw, fr)
  15. //handleError( err )
  16. }

通过这样的修改,文件将以xyz/...的形式放入tar文件中。希望对你有帮助!

英文:

I have been using this code to write to a tar file. I am calling it like
err = retarIt(dirTopDebug, path), where dirTopDebug is the path to my tar file (/tmp/abc.tar), and path is the path of files I want to add (/tmp/xyz/...). When I am untarring the generated tar file, I find that inside abc.tar files are put in /tmp/xyz/.. format. But I want them inside tar like xyz/..., i.e. without the tmp folder.

How can I do that?

  1. func TarGzWrite(_path string, tw *tar.Writer, fi os.FileInfo) {
  2. fr, _ := os.Open(_path)
  3. //handleError(err)
  4. defer fr.Close()
  5. h := new(tar.Header)
  6. h.Name = _path
  7. h.Size = fi.Size()
  8. h.Mode = int64(fi.Mode())
  9. h.ModTime = fi.ModTime()
  10. err := tw.WriteHeader(h)
  11. if err != nil {
  12. panic(err)
  13. }
  14. _, _ = io.Copy(tw, fr)
  15. //handleError( err )
  16. }
  17. func IterDirectory(dirPath string, tw *tar.Writer) {
  18. dir, _ := os.Open(dirPath)
  19. //handleError( err )
  20. defer dir.Close()
  21. fis, _ := dir.Readdir(0)
  22. //handleError( err )
  23. for _, fi := range fis {
  24. fmt.Println(dirPath)
  25. curPath := dirPath + "/" + fi.Name()
  26. if fi.IsDir() {
  27. //TarGzWrite( curPath, tw, fi )
  28. IterDirectory(curPath, tw)
  29. } else {
  30. fmt.Printf("adding... %s\n", curPath)
  31. TarGzWrite(curPath, tw, fi)
  32. }
  33. }
  34. }
  35. func retarIt(outFilePath, inPath string) error {
  36. fw, err := os.Create(outFilePath)
  37. if err != nil {
  38. return err
  39. }
  40. defer fw.Close()
  41. gw := gzip.NewWriter(fw)
  42. defer gw.Close()
  43. // tar write
  44. tw := tar.NewWriter(gw)
  45. defer tw.Close()
  46. IterDirectory(inPath, tw)
  47. fmt.Println("tar.gz ok")
  48. return nil
  49. }

答案1

得分: 1

无论tar头中指定了什么名称,都会被使用。使用strings包中的strings.LastIndex(或strings.Index)函数来分离到/tmp为止的部分。

因此,如果上面的TarGzWrite函数的代码修改如下,它将按照您的要求工作(注意:您可能需要将strings.LastIndex替换为strings.Index)。

  1. //TarGzWrite函数与上面相同...
  2. h := new(tar.Header)
  3. //此后是新代码...
  4. lastIndex := strings.LastIndex(_path, "/tmp")
  5. fmt.Println("字符串是", _path, "最后索引是", lastIndex)
  6. var name string
  7. if lastIndex > 0 {
  8. name = _path[lastIndex+len("/tmp")+1:]
  9. fmt.Println("得到的名称:", name)
  10. } else {
  11. //这不是必需的,但只是为了测试我的代码而存在
  12. name = _path
  13. }
  14. // h.Name = _path
  15. h.Name = name
  16. h.Size = fi.Size()
  17. h.Mode = int64(fi.Mode())
英文:

Whatever name is specified in the tar header, is used. Use the strings.LastIndex (or strings.Index) function of the strings package to separate the part till /tmp.

So if the code in TarGzWrite function above is modified as follows it works the way you want (note: you may want to replace strings.LastIndex below with strings.Index).

  1. //TarGzWrite function same as above....
  2. h := new(tar.Header)
  3. //New code after this..
  4. lastIndex := strings.LastIndex(_path, "/tmp")
  5. fmt.Println("String is ", _path, "Last index is", lastIndex)
  6. var name string
  7. if lastIndex > 0 {
  8. name = _path[lastIndex+len("/tmp")+1:]
  9. fmt.Println("Got name:", name)
  10. } else {
  11. //This would not be needed, but was there just for testing my code
  12. name = _path
  13. }
  14. // h.Name = _path
  15. h.Name = name
  16. h.Size = fi.Size()
  17. h.Mode = int64(fi.Mode())

huangapple
  • 本文由 发表于 2017年4月12日 15:59:48
  • 转载请务必保留本文链接:https://go.coder-hub.com/43363650.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定