diff --git a/src/SharpCompress/Archives/IArchiveExtensions.cs b/src/SharpCompress/Archives/IArchiveExtensions.cs
index 14a48dbd..56ea0d9f 100644
--- a/src/SharpCompress/Archives/IArchiveExtensions.cs
+++ b/src/SharpCompress/Archives/IArchiveExtensions.cs
@@ -1,4 +1,9 @@
+using System;
+using System.Collections.Generic;
+using System.IO;
using System.Linq;
+using System.Threading;
+using System.Threading.Tasks;
using SharpCompress.Common;
namespace SharpCompress.Archives;
@@ -19,4 +24,54 @@ public static class IArchiveExtensions
entry.WriteToDirectory(destinationDirectory, options);
}
}
+
+ ///
+ /// Extracts the archive to the destination directory. Directories will be created as needed.
+ ///
+ /// The archive to extract.
+ /// The folder to extract into.
+ /// Optional progress report callback.
+ /// Optional cancellation token.
+ public static void ExtractToDirectory(
+ this IArchive archive,
+ string destination,
+ Action? progressReport = null,
+ CancellationToken cancellationToken = default
+ )
+ {
+ // Prepare for progress reporting
+ var totalBytes = archive.TotalUncompressSize;
+ var bytesRead = 0L;
+
+ // Tracking for created directories.
+ var seenDirectories = new HashSet();
+
+ // Extract
+ var entries = archive.ExtractAllEntries();
+ while (entries.MoveToNextEntry())
+ {
+ cancellationToken.ThrowIfCancellationRequested();
+
+ var entry = entries.Entry;
+ if (entry.IsDirectory)
+ {
+ continue;
+ }
+
+ // Create each directory
+ var path = Path.Combine(destination, entry.Key);
+ if (Path.GetDirectoryName(path) is { } directory && seenDirectories.Add(path))
+ {
+ Directory.CreateDirectory(directory);
+ }
+
+ // Write file
+ using var fs = File.OpenWrite(path);
+ entries.WriteEntryTo(fs);
+
+ // Update progress
+ bytesRead += entry.Size;
+ progressReport?.Invoke(bytesRead / (double)totalBytes);
+ }
+ }
}