diff --git a/libraries-apache-commons-2/README.md b/libraries-apache-commons-2/README.md
new file mode 100644
index 0000000000..7f91a737d5
--- /dev/null
+++ b/libraries-apache-commons-2/README.md
@@ -0,0 +1,7 @@
+## Apache Commons
+
+This module contains articles about Apache Commons libraries.
+
+### Relevant articles
+
+- More articles: [[<--prev]](../libraries-apache-commons)
\ No newline at end of file
diff --git a/libraries-apache-commons-2/log4j.properties b/libraries-apache-commons-2/log4j.properties
new file mode 100644
index 0000000000..2173c5d96f
--- /dev/null
+++ b/libraries-apache-commons-2/log4j.properties
@@ -0,0 +1 @@
+log4j.rootLogger=INFO, stdout
diff --git a/libraries-apache-commons-2/pom.xml b/libraries-apache-commons-2/pom.xml
new file mode 100644
index 0000000000..d771aac9ab
--- /dev/null
+++ b/libraries-apache-commons-2/pom.xml
@@ -0,0 +1,39 @@
+
+
+    4.0.0
+    libraries-apache-commons-2
+    libraries-apache-commons-2
+
+    
+        com.baeldung
+        parent-modules
+        1.0.0-SNAPSHOT
+    
+
+    
+        
+            org.apache.commons
+            commons-compress
+            ${commons-compress.version}
+        
+        
+            org.apache.ant
+            ant
+            ${ant.version}
+        
+        
+            org.apache.commons
+            commons-vfs2
+            ${commons-vfs2.version}
+        
+    
+
+    
+        1.23.0
+        1.10.13
+        2.9.0
+    
+
+
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/Resources.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/Resources.java
new file mode 100644
index 0000000000..15e71eb156
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/Resources.java
@@ -0,0 +1,14 @@
+package com.baeldung.commons.untar;
+
+import java.io.InputStream;
+
+public interface Resources {
+
+    static InputStream tarFile() {
+        return Resources.class.getResourceAsStream("/untar/test.tar");
+    }
+
+    static InputStream tarGzFile() {
+        return Resources.class.getResourceAsStream("/untar/test.tar.gz");
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/TarExtractor.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/TarExtractor.java
new file mode 100644
index 0000000000..73a54bba44
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/TarExtractor.java
@@ -0,0 +1,39 @@
+package com.baeldung.commons.untar;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+
+public abstract class TarExtractor {
+
+    private InputStream tarStream;
+    private boolean gzip;
+    private Path destination;
+
+    protected TarExtractor(InputStream in, boolean gzip, Path destination) throws IOException {
+        this.tarStream = in;
+        this.gzip = gzip;
+        this.destination = destination;
+
+        Files.createDirectories(destination);
+    }
+
+    protected TarExtractor(Path tarFile, Path destination) throws IOException {
+        this(Files.newInputStream(tarFile), tarFile.endsWith("gz"), destination);
+    }
+
+    public Path getDestination() {
+        return destination;
+    }
+
+    public InputStream getTarStream() {
+        return tarStream;
+    }
+
+    public boolean isGzip() {
+        return gzip;
+    }
+
+    public abstract void untar() throws IOException;
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorAnt.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorAnt.java
new file mode 100644
index 0000000000..5bb4d74beb
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorAnt.java
@@ -0,0 +1,37 @@
+package com.baeldung.commons.untar.impl;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+import java.util.zip.GZIPInputStream;
+
+import org.apache.tools.tar.TarEntry;
+import org.apache.tools.tar.TarInputStream;
+
+import com.baeldung.commons.untar.TarExtractor;
+
+public class TarExtractorAnt extends TarExtractor {
+
+    public TarExtractorAnt(InputStream in, boolean gzip, Path destination) throws IOException {
+        super(in, gzip, destination);
+    }
+
+    @Override
+    public void untar() throws IOException {
+        try (TarInputStream tar = new TarInputStream(new BufferedInputStream( //
+                isGzip() ? new GZIPInputStream(getTarStream()) : getTarStream()))) {
+            TarEntry entry;
+            while ((entry = tar.getNextEntry()) != null) {
+                Path extractTo = getDestination().resolve(entry.getName());
+                if (entry.isDirectory()) {
+                    Files.createDirectories(extractTo);
+                } else {
+                    Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorCommonsCompress.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorCommonsCompress.java
new file mode 100644
index 0000000000..4981426c35
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorCommonsCompress.java
@@ -0,0 +1,38 @@
+package com.baeldung.commons.untar.impl;
+
+import java.io.BufferedInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
+
+import org.apache.commons.compress.archivers.ArchiveEntry;
+import org.apache.commons.compress.archivers.tar.TarArchiveInputStream;
+import org.apache.commons.compress.compressors.gzip.GzipCompressorInputStream;
+
+import com.baeldung.commons.untar.TarExtractor;
+
+public class TarExtractorCommonsCompress extends TarExtractor {
+
+    public TarExtractorCommonsCompress(InputStream in, boolean gzip, Path destination) throws IOException {
+        super(in, gzip, destination);
+    }
+
+    @Override
+    public void untar() throws IOException {
+        try (BufferedInputStream inputStream = new BufferedInputStream(getTarStream()); //
+            TarArchiveInputStream tar = new TarArchiveInputStream( //
+                isGzip() ? new GzipCompressorInputStream(inputStream) : inputStream)) {
+            ArchiveEntry entry;
+            while ((entry = tar.getNextEntry()) != null) {
+                Path extractTo = getDestination().resolve(entry.getName());
+                if (entry.isDirectory()) {
+                    Files.createDirectories(extractTo);
+                } else {
+                    Files.copy(tar, extractTo, StandardCopyOption.REPLACE_EXISTING);
+                }
+            }
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorVfs.java b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorVfs.java
new file mode 100644
index 0000000000..291fcebfb0
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/java/com/baeldung/commons/untar/impl/TarExtractorVfs.java
@@ -0,0 +1,48 @@
+package com.baeldung.commons.untar.impl;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.nio.file.StandardCopyOption;
+
+import org.apache.commons.vfs2.FileContent;
+import org.apache.commons.vfs2.FileObject;
+import org.apache.commons.vfs2.FileSystemManager;
+import org.apache.commons.vfs2.FileType;
+import org.apache.commons.vfs2.VFS;
+
+import com.baeldung.commons.untar.TarExtractor;
+
+public class TarExtractorVfs extends TarExtractor {
+
+    public TarExtractorVfs(InputStream in, boolean gzip, Path destination) throws IOException {
+        super(in, gzip, destination);
+    }
+
+    @Override
+    public void untar() throws IOException {
+        Path tmpTar = Files.createTempFile("temp", isGzip() ? ".tar.gz" : ".tar");
+        Files.copy(getTarStream(), tmpTar, StandardCopyOption.REPLACE_EXISTING);
+
+        FileSystemManager fsManager = VFS.getManager();
+        String uri = String.format("%s:file://%s", isGzip() ? "tgz" : "tar", tmpTar);
+        FileObject tar = fsManager.resolveFile(uri);
+
+        for (FileObject entry : tar) {
+            Path extractTo = Paths.get(getDestination().toString(), entry.getName()
+                .getPath());
+
+            if (entry.isReadable() && entry.getType() == FileType.FILE) {
+                Files.createDirectories(extractTo.getParent());
+
+                try (FileContent content = entry.getContent(); InputStream stream = content.getInputStream()) {
+                    Files.copy(stream, extractTo, StandardCopyOption.REPLACE_EXISTING);
+                }
+            }
+        }
+
+        Files.delete(tmpTar);
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/main/resources/logback.xml b/libraries-apache-commons-2/src/main/resources/logback.xml
new file mode 100644
index 0000000000..7d900d8ea8
--- /dev/null
+++ b/libraries-apache-commons-2/src/main/resources/logback.xml
@@ -0,0 +1,13 @@
+
+
+    
+        
+            %d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n
+            
+        
+    
+
+    
+        
+    
+
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorAntUnitTest.java b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorAntUnitTest.java
new file mode 100644
index 0000000000..0b39f49884
--- /dev/null
+++ b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorAntUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.commons.untar;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import org.junit.Test;
+
+import com.baeldung.commons.untar.impl.TarExtractorAnt;
+
+public class TarExtractorAntUnitTest {
+
+    @Test
+    public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/ant");
+
+        new TarExtractorAnt(Resources.tarFile(), false, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+
+    @Test
+    public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/ant-gz");
+
+        new TarExtractorAnt(Resources.tarGzFile(), true, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+}
diff --git a/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorCommonsCompressUnitTest.java b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorCommonsCompressUnitTest.java
new file mode 100644
index 0000000000..e9c7d701d3
--- /dev/null
+++ b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorCommonsCompressUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.commons.untar;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import org.junit.jupiter.api.Test;
+
+import com.baeldung.commons.untar.impl.TarExtractorCommonsCompress;
+
+public class TarExtractorCommonsCompressUnitTest {
+
+    @Test
+    public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/commons-compress");
+
+        new TarExtractorCommonsCompress(Resources.tarFile(), false, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+
+    @Test
+    public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/commons-compress-gz");
+
+        new TarExtractorCommonsCompress(Resources.tarGzFile(), true, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorVfsUnitTest.java b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorVfsUnitTest.java
new file mode 100644
index 0000000000..d5e9004732
--- /dev/null
+++ b/libraries-apache-commons-2/src/test/java/com/baeldung/commons/untar/TarExtractorVfsUnitTest.java
@@ -0,0 +1,40 @@
+package com.baeldung.commons.untar;
+
+import static org.junit.jupiter.api.Assertions.assertTrue;
+
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.stream.Stream;
+
+import org.junit.Test;
+
+import com.baeldung.commons.untar.impl.TarExtractorVfs;
+
+public class TarExtractorVfsUnitTest {
+
+    @Test
+    public void givenTarFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/vfs");
+
+        new TarExtractorVfs(Resources.tarFile(), false, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+
+    @Test
+    public void givenTarGzFile_whenUntar_thenExtractedToDestination() throws IOException {
+        Path destination = Paths.get("/tmp/vfs-gz");
+
+        new TarExtractorVfs(Resources.tarGzFile(), true, destination).untar();
+
+        try (Stream files = Files.list(destination)) {
+            assertTrue(files.findFirst()
+                .isPresent());
+        }
+    }
+}
\ No newline at end of file
diff --git a/libraries-apache-commons-2/src/test/resources/untar/test.tar b/libraries-apache-commons-2/src/test/resources/untar/test.tar
new file mode 100644
index 0000000000..a0c9e8714f
Binary files /dev/null and b/libraries-apache-commons-2/src/test/resources/untar/test.tar differ
diff --git a/libraries-apache-commons-2/src/test/resources/untar/test.tar.gz b/libraries-apache-commons-2/src/test/resources/untar/test.tar.gz
new file mode 100644
index 0000000000..99bc3ec933
Binary files /dev/null and b/libraries-apache-commons-2/src/test/resources/untar/test.tar.gz differ
diff --git a/libraries-apache-commons/README.md b/libraries-apache-commons/README.md
index aceea3282a..9623ecca2f 100644
--- a/libraries-apache-commons/README.md
+++ b/libraries-apache-commons/README.md
@@ -13,4 +13,5 @@ This module contains articles about Apache Commons libraries.
 - [Apache Commons BeanUtils](https://www.baeldung.com/apache-commons-beanutils)
 - [Histograms with Apache Commons Frequency](https://www.baeldung.com/apache-commons-frequency)
 - [An Introduction to Apache Commons Lang 3](https://www.baeldung.com/java-commons-lang-3)
-- [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](https://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library)
\ No newline at end of file
+- [Differences Between the Java WatchService API and the Apache Commons IO Monitor Library](https://www.baeldung.com/java-watchservice-vs-apache-commons-io-monitor-library)
+More articles: [[next-->]](../libraries-apache-commons-2)
\ No newline at end of file
diff --git a/pom.xml b/pom.xml
index 0091f57913..6d566549ef 100644
--- a/pom.xml
+++ b/pom.xml
@@ -867,6 +867,7 @@
                 libraries-6
 
                 libraries-apache-commons
+                libraries-apache-commons-2
                 libraries-apache-commons-collections
                 libraries-apache-commons-io
                 libraries-data-2
@@ -1135,6 +1136,7 @@
                 libraries-5
                 libraries-6
                 libraries-apache-commons
+                libraries-apache-commons-2
                 libraries-apache-commons-collections
                 libraries-apache-commons-io
                 libraries-data-2