DEV Community

loading...
Cover image for Extract Zip files recursively with NodeJS

Extract Zip files recursively with NodeJS

Praveen Saraogi
Software Engineer ๐Ÿ‘จโ€๐Ÿ’ป @Paytm | Previously http://bewakoof.com | Ex-Infoscion | JavaScript ๐Ÿ’ป | ReactJS โš› | VueJS ๐Ÿš€
ใƒป3 min read

Hello Coders ๐Ÿ‘‹

This is my first attempt at writing a technical post. Hope you find it helpful.

Problem Statement

Recently, I encountered a requirement where I had to extract all the zip files present inside a main zip file which had a random folder structure and any of the folders can have a zip file present inside it at any level.

Breaking down of the problem

  1. Find Library for extracting
  2. Extract the main zip file i.e demo.zip
  3. Figure out a way to traverse the whole folder structure recursively
  4. Then extract the .zip file whenever it is found.

Solution

extract-zip library used to extract the zip files.

Method to extract zip file

  • It takes two input arguments source and target. source should be absolute path of the zip file, target is where the folder will get extracted.
async function extractZip(source, target) {
  try {
    await extract(source, { dir: target });
    console.log("Extraction complete");
  } catch (err) {
    console.log("Oops: extractZip failed", err);
  }
}
Enter fullscreen mode Exit fullscreen mode

Method to traverse folders recursively

const unzipFiles = async function (dirPath) {
  const files = fs.readdirSync(dirPath);

  await Promise.all(
    files.map(async (file) => {
      if (fs.statSync(dirPath + "/" + file).isDirectory()) {
        await unzipFiles(dirPath + "/" + file);
      } else {
        const fullFilePath = path.join(dirPath, "/", file);
        const folderName = file.replace(".zip", "");
        if (file.endsWith(".zip")) {
          zippedFiles.push(folderName);
          await extractZip(fullFilePath, path.join(dirPath, "/", folderName));
          await unzipFiles(path.join(dirPath, "/", folderName));
        }
      }
    })
  );
};
Enter fullscreen mode Exit fullscreen mode

Lot of activities in above snippet. Let's decode

  • dirPath : file extraction path

  • The fs.readdirSync() method is used to synchronously read the contents of a given directory. The method returns an array with all the file names or objects in the directory.

  • Now, the main challenge was to loop through all the folders/files asynchronously. We cannot use forEach since it doesn't support async/await keyword. Traditional for loop syntax works with await keyword. But I wanted to use the more common array method map().

  • If you use await with map() it returns array of promises. Hence, to resolve all promises await Promise.all(arrayOfPromises) is used here.

  • For more details on async/await in loops refer to this wonderful article

if (fs.statSync(dirPath + "/" + file).isDirectory()) {
        await unzipFiles(dirPath + "/" + file);
      }
Enter fullscreen mode Exit fullscreen mode
  • To check whether current object is file or folder isDirectory() method is used. If its a folder then call same method again i.e unzipFiles()
else {
        const fullFilePath = path.join(dirPath, "/", file);
        const folderName = file.replace(".zip", "");
        if (file.endsWith(".zip")) {
          zippedFiles.push(folderName);
          await extractZip(fullFilePath, path.join(dirPath, "/", folderName));
          await unzipFiles(path.join(dirPath, "/", folderName));
        }
Enter fullscreen mode Exit fullscreen mode
  • If a file is found then we will call the extractZip() method with source and target with their absolute paths.

  • If we don't specify the target, or give it a current path then it will extract all the files in current directory itself. But I wanted to extract the zip to their respective folder names.

  • To achieve this, I have spliced the folder name from .zip file passed it as a target to extractZip() method.

  • Now there is one more catch in the last line i.e

await unzipFiles(path.join(dirPath, "/", folderName));
Enter fullscreen mode Exit fullscreen mode
  • Since there is a possibility that the extracted files can also have zip files inside it, so as soon as we extract any file we will again have to call unzipFiles() to traverse through the extracted files.

Output will be -
Alt Text


Thanks a lot for reading ๐Ÿ™

If you enjoyed this article or found it helpful, give it a thumbs-up ๐Ÿ‘

Feel free to connect ๐Ÿ‘‹

Twitter | LinkedIn

Discussion (2)

Collapse
aashishkushwaha profile image
Aashish Kushwaha

This is amazing ๐Ÿ‘๐Ÿ™Œ

Collapse
kanade_sourabh profile image
Sourabh Kanade

Its great๐Ÿค™