node.jsimage-conversionsharp

Bulk Convert Entire Folder of Images with sharp


I have a project where I need to bulk convert large amounts of .png files to .jpgs, with some control over compression quality. Using the node module sharp works like a charm on individual files, e.g.:

const sharp = require("sharp");

sharp("input/82.png")
  .toFormat("jpeg")
  .jpeg({ quality: 70 })
  .toFile("output/82.jpg");

But I have hundreds of files I need to convert at a shot. I had hoped to be able to use some wildcard for files, like:

sharp("input/*.png")
  .toFormat("jpeg")
  .jpeg({ quality: 70 })
  .toFile("output/*.jpg");

though that of course doesn't work, nor has any attempt I've done to loop through all the files, or using the node module glob. Appreciate any guidance that can be provided here.


Solution

  • With the help of another developer, the answer turned out to be a bit more complex than I anticipated, and requires the use of the node module glob:

    // example run : node sharp-convert.js ~/Projects/docs/public/images/output/new
    
    const fs = require('fs');
    const process = require('process');
    const path = require('path');
    const glob = require("glob")
    
    
    const dir = process.argv[2];
    
    const input_path = path.join(dir, '**', '*.png');
    const output_path = path.join(dir, "min");
    
    const sharp = require('sharp');
    
    glob(input_path, function (err, files) {
      if (err != null) { throw err; }
      fs.mkdirSync(output_path, { recursive: true });
      files.forEach(function(inputFile) {
      sharp(inputFile)
        .jpeg({ mozjpeg: true, quality: 60, force: true })
        .toFile(path.join(output_path, path.basename(inputFile, path.extname(inputFile))+'.jpg'), (err, info) => {
          if(err === null){
              fs.unlink(inputFile, (err2) => {
                  if (err2) throw err2;
                  console.log('successfully compressed and deleted '+inputFile);
              });
          } else { throw err }
        });
      });
    });
    

    NOTE: This method is destructive and will delete any existing .pngs. Make sure to have a backup of your originals.