0

I am looking to create a .tar.gz file of the following folder/directory structure, while retaining the same folder/ directory structure

ParentDir\
    ChildDir1\
        -file1
    ChildDir2\
        -file2
        -file3
    ChildDir3\
        -file4
        -file5

However I am only able to create a .tar.gz of all the files, without the folder/directory structure. ie: ParentDir.tar.gz

    ParentDir\
        -file1
        -file2
        -file3
        -file4
        -file5

Using the user accepted answer in Compress directory to tar.gz with Commons Compress, I have the following code:

public void exportStaticFilesTar(String appID) throws, Exception {
        
        FileOutputStream fOut = null;
        BufferedOutputStream bOut = null;
        GzipCompressorOutputStream gzOut = null;
        TarArchiveOutputStream tOut = null;

        try {
            String filename = "ParentDir.tar.gz"

            //"parent/childDirToCompress/"
            String path = "<path to ParentDir>";

            fOut = new FileOutputStream(new File(filename));
            bOut = new BufferedOutputStream(fOut);
            gzOut = new GzipCompressorOutputStream(bOut);
            tOut = new TarArchiveOutputStream(gzOut);
            
            addFileToTarGz(tOut, path, "");
        } catch (Exception e) {
            log.error("Error creating .tar.gz: " +e);
        } finally {
            tOut.finish();
            tOut.close();
            gzOut.close();
            bOut.close();
            fOut.close();
        }
        
        //Download the file locally
        
    }

    private void addFileToTarGz(TarArchiveOutputStream tOut, String path, String base) throws IOException {
        File f = new File(path);
        String entryName = base + f.getName();
        TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName);
        tOut.putArchiveEntry(tarEntry);
        if (f.isFile()) {
            IOUtils.copy(new FileInputStream(f), tOut);
            tOut.closeArchiveEntry();
        } else {
            tOut.closeArchiveEntry();
            File[] children = f.listFiles();
            if (children != null) {
                for (File child : children) {
                    addFileToTarGz(tOut, child.getAbsolutePath(), entryName + "/");
                }
            }
        }
    }

Can someone please advice, how I can modify the current code to retain the folder/directory structure when creating a .tar.gz file. Thanks!

Mark Adler
  • 101,978
  • 13
  • 118
  • 158
user1971376
  • 93
  • 1
  • 4
  • 10

2 Answers2

1

I get on better with the following. Important: you need to pass as base the correct initial value which is the first directory in the tree (excluding the fs root):

    private void addFileToTarGz(TarArchiveOutputStream tOut, String path, String base) throws IOException {
        File f = new File(path);
        String entryName = base + File.separatorChar + f.getName();
        TarArchiveEntry tarEntry = new TarArchiveEntry(f, entryName);
        tOut.putArchiveEntry(tarEntry);
        if (f.isFile()) {
            IOUtils.copy(new FileInputStream(f), tOut);
            tOut.closeArchiveEntry();
        } else {
            tOut.closeArchiveEntry();
            File[] children = f.listFiles();
            if (children != null) {
                for (File child : children) {
                    addFileToTarGz(tOut, child.getAbsolutePath(), entryName);
                }
            }
        }
    }
g00se
  • 3,207
  • 2
  • 5
  • 9
1

Using the code mentioned in the request, I was able to generate a successful compressed file on my linux system.

You can replicate by changing user path and the root folder which needs to be compressed.

public static void createTarGZ() throws FileNotFoundException, IOException
    {
        String sourceDirectoryPath = null;
        String destinationTarGzPath = null;
        FileOutputStream fileOutputStream = null;
        BufferedOutputStream bufferedOutputStream = null;
        GzipCompressorOutputStream gzOutpuStream = null;
        TarArchiveOutputStream tarArchiveOutputStream = null;

        String basePath = "/home/saad/CompressionTest/";

        try
        {

            sourceDirectoryPath = basePath + "asterisk";
            destinationTarGzPath = basePath + "asterisk.tar.gz";

            fileOutputStream = new FileOutputStream(new File(destinationTarGzPath));
            bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
            gzOutpuStream = new GzipCompressorOutputStream(bufferedOutputStream);
            tarArchiveOutputStream = new TarArchiveOutputStream(gzOutpuStream);

            addFileToTarGz(tarArchiveOutputStream, sourceDirectoryPath, "");
        }
        finally
        {
            tarArchiveOutputStream.finish();
            tarArchiveOutputStream.close();
            gzOutpuStream.close();
            bufferedOutputStream.close();
            fileOutputStream.close();
        }
    }

    private static void addFileToTarGz(TarArchiveOutputStream tarOutputStream, String path, String base) throws IOException
    {
        File fileToCompress = new File(path);

        String entryName = base + fileToCompress.getName();

        TarArchiveEntry tarEntry = new TarArchiveEntry(fileToCompress, entryName);

        tarOutputStream.putArchiveEntry(tarEntry);

        // If its a file, simply add it
        if (fileToCompress.isFile())
        {
            IOUtils.copy(new FileInputStream(fileToCompress), tarOutputStream);
            tarOutputStream.closeArchiveEntry();
        }
        // If its a folder then add all its contents
        else
        {
            tarOutputStream.closeArchiveEntry();
            File[] children = fileToCompress.listFiles();

            if (children != null)
            {
                // add every file/folder recursively to the tar
                for (File child : children)
                {
                    addFileToTarGz(tarOutputStream, child.getAbsolutePath(), entryName + "/");
                }
            }
        }
    }
saadeez
  • 111
  • 4