How to Extract Compressed Files in Specific Subdirectories Using JShell

Have you ever had to extract a large number of compressed files, but wanted to keep them organized in specific subdirectories? Manually extracting each file can be time-consuming and error-prone, especially if you have to do it for hundreds or thousands of files. In this tutorial, we’ll show you how to use JShell to automate the process of extracting compressed files into their corresponding subdirectories.

Prerequisites

Before we begin, you’ll need to have the following:

  • Java Development Kit (JDK) 9 or later installed on your system
  • Basic familiarity with the command line
  • Some compressed files to extract (in this example, we’ll use ZIP, GZIP, and TAR files)

Step 1: Launch JShell

JShell is an interactive Java shell that allows you to test and run Java code snippets without having to create a full Java program. To launch JShell, open a command prompt or terminal window and enter the following command:

jshell

Once you see the JShell prompt (which looks like “jshell>”), you’re ready to start entering Java code.

Step 2: Define the Root Directory

The first thing we need to do is define the root directory that we want to search for compressed files. In our example, we’ll use the directory “/path/to/root/directory”. Replace this with the path to the directory that you want to search.

Path root = Paths.get("/path/to/root/directory");

Step 3: Define a Method to Extract Compressed Files

Next, we’ll define a method that can extract a compressed file to its corresponding subdirectory. This method will take a Path object representing the compressed file as its argument.

void extractCompressedFile(Path compressedFile) {
    // Code for extracting the file goes here
}

Inside this method, we’ll determine the subdirectory to extract the file to based on the name of the compressed file. We’ll then create the subdirectory if it doesn’t already exist, and extract the file based on its type (ZIP, GZIP, or TAR).

We’ll use the Apache Commons Compress library to handle different types of compressed files. You will need to download and include the library in your classpath in order for this script to work.

Here’s the full code for the extractCompressedFile method:

import java.io.*;
import java.nio.file.*;
import java.util.zip.*;
import org.apache.commons.compress.archivers.*;
import org.apache.commons.compress.archivers.tar.*;
import org.apache.commons.compress.compressors.gzip.*;

// Define the root directory to search
Path root = Paths.get("/path/to/root/directory");

// Define a method to extract a compressed file to its corresponding subdirectory
void extractCompressedFile(Path compressedFile) {
    try {
        // Determine the subdirectory to extract the file to
        Path subdirectory = compressedFile.getParent().resolve(compressedFile.getFileName().toString().replaceAll("\\.(zip|gz|tar)$", ""));
        
        // Create the subdirectory if it doesn't already exist
        Files.createDirectories(subdirectory);
        
        // Extract the file based on its type
        if (compressedFile.toString().endsWith(".zip")) {
            ZipFile zipFile = new ZipFile(compressedFile.toFile());
            zipFile.stream().forEach(entry -> {
                try {
                    Path outputPath = subdirectory.resolve(entry.getName());
                    if (entry.isDirectory()) {
                        Files.createDirectories(outputPath);
                    } else {
                        InputStream inputStream = zipFile.getInputStream(entry);
                        Files.copy(inputStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            });
            zipFile.close();
        } else if (compressedFile.toString().endsWith(".gz")) {
            FileInputStream inputStream = new FileInputStream(compressedFile.toFile());
            GzipCompressorInputStream gzInputStream = new GzipCompressorInputStream(inputStream);
            Files.copy(gzInputStream, subdirectory.resolve(compressedFile.getFileName().toString().replaceAll("\\.gz$", "")), StandardCopyOption.REPLACE_EXISTING);
            gzInputStream.close();
        } else if (compressedFile.toString().endsWith(".tar")) {
            FileInputStream inputStream = new FileInputStream(compressedFile.toFile());
            TarArchiveInputStream tarInputStream = new TarArchiveInputStream(inputStream);
            TarArchiveEntry entry = null;
            while ((entry = tarInputStream.getNextTarEntry()) != null) {
                Path outputPath = subdirectory.resolve(entry.getName());
                if (entry.isDirectory()) {
                    Files.createDirectories(outputPath);
                } else {
                    Files.copy(tarInputStream, outputPath, StandardCopyOption.REPLACE_EXISTING);
                }
            }
            tarInputStream.close();
        }
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// Define a method to traverse the directory and extract compressed files
void traverseDirectory(Path directory) {
    try {
        // Iterate over the contents of the directory
        DirectoryStream<Path> stream = Files.newDirectoryStream(directory);
        for (Path path : stream) {
            if (Files.isDirectory(path)) {
                // Recursively traverse subdirectories
                traverseDirectory(path);
            } else if (path.toString().matches(".*\\.(zip|gz|tar)$")) {
                // Extract compressed files
                extractCompressedFile(path);
            }
        }
        stream.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}

// Call the traverseDirectory method with the root directory as the argument
traverseDirectory(root);

Discover more from Armel Nene's blog

Subscribe now to keep reading and get access to the full archive.

Continue reading