nn2202
nn2202

Reputation: 43

C# - extract specific directory from ZIP, preserving folder structure

I have a zip archive and the folder structure inside of an archive looks something like this:

+ dirA
  - fileA.txt
  + dirB
    - fileB.txt

I'm trying to extract the contents of dirA to disk, but while doing so, I'm unable to perserve the folder structure, and instead of

  - fileA.txt
  + dirB
    - fileB.txt

I get

  - fileA.txt
  - fileB.txt

Here's my code:

using (ZipArchive archive = ZipFile.OpenRead(archivePath)) // archivePath is path to the zip archive
{
    // get the root directory
    var root = archive.Entries[0]?.FullName;
    if (root == null) { 
        // quit in a nice way
    }
    var result = from curr in archive.Entries
                 where Path.GetDirectoryName(curr.FullName) != root
                 where !string.IsNullOrEmpty(curr.Name)
                 select curr;

    foreach (ZipArchiveEntry entry in result)
    {
        string path = Path.Combine(extractPath, entry.Name); // extractPath is somwhere on the disk
        entry.ExtractToFile(path);
    }
}

I'm pretty positive that's because I use entry.Name instead of entry.FullName in Path.Combine(), but if I were to use FullName, I would have in path that root directory dirA I'm trying not to extract. So I've hit a wall here, and the only solution I can think of is extracting the whole zip with:

ZipFile.ExtractToDirectory(archivePath, extractPath);

...and then moving the subfolders from dirA to a different location and deleting dirA. Which doesn't seem like the luckiest of ideas.

Any help is much appreciated.

Upvotes: 4

Views: 4269

Answers (1)

Petr Vávro
Petr Vávro

Reputation: 1516

You could just shorten the FullName by the part of the path you dont want:

foreach (ZipArchiveEntry entry in result)
{
    var newName = entry.FullName.Substring(root.Length);
    string path = Path.Combine(extractPath, newName);

    if (!Directory.Exists(path))
        Directory.CreateDirectory(Path.GetDirectoryName(path));

    entry.ExtractToFile(path);
}

Upvotes: 5

Related Questions