2016-09-22 1 views
1

У меня возникли проблемы с поиском, как написать каталог в headerinfo tarball. Например, у меня есть эта структура каталогов:Golang tarring directory

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

Если я очернить вверх тест, используя мой Go дегтя исполняемым, он будет распаковка и иметь первоначальную структуру. Если я делаю деготь -tvf на тарболе, список будет:

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

Однако, если я вручную сделать деготь -cvf теста, а затем сделать деготь -tvf, список будет:

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

Это то, что я хочу, чтобы моя программа для торможения Go также сделала. В моей программе Go я попытался добавить новый метод writeDirToTar, чтобы иметь дело с добавлением каталогов в tarWriter. Я вызываю либо writeFileToTar, либо writeDirToTar из функции fileWalk. Я получаю ошибку «test/subDirA is directory», когда я вызываю io.Copy(tarWriter, file) в writeDirToTar, какой смысл имеет смысл. Есть ли обходной путь для этого?

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 

} 

ответ

1

Вы упускаете Typeflag поле в tar.Header.

Для каталога вы хотите, по крайней мере:

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

Вы не хотите, размера здесь, и вы не хотите, чтобы скопировать данные каталога, так как внутренние структуры данных каталога ничего не значат деготь ,

Вы также можете добавить / к имени файла, чтобы визуально указать его каталог и соответствовать поведению POSIX tar.

В качестве альтернативы вы можете просто использовать функцию tar.FileInfoHeader так же, как вы делали с файлами, чтобы создать правильную структуру заголовка.