EXIF rename script

Photo filenames from iPhone comes in a sequence, not to my liking for archival. Here comes JavaScript scripting…

const util = require('util');
const fs = require('fs');
const path = require('path');
const moment = require('moment');  // npm i moment
const ExifImage = util.promisify(require('exif').ExifImage);  // npm i exif

const folder = process.argv[2]; // '/var/services/photo/...';
fs.readdirSync(folder)
  .filter(file => /IMG_\d{4}\.JPG$/i.test(file))
  .forEach(file => {
    const oldName = path.join(folder, file);
    new ExifImage({ image:oldName }, function(error, data) {
      if (!data) return;
      const taken = moment(data.exif.DateTimeOriginal, 'YYYY:MM:DD HH:mm:ss');
      if (!taken.isValid()) return;
      const newName = taken.format('[IMG]_YYYYMMDD_HHmmss[.jpg]');
      console.log(file, taken, newName);
      // fs.renameSync(oldName, path.join(folder, newName));
    });
  });

Activate the rename after testing the script, or upgrade it with argv control.

And then comes HEIC. Let’s try another library.

const util = require('util');
const fs = require('fs');
const path = require('path');
const moment = require('moment');  // npm i moment
const exifr = require('exifr'); // npm i exifr

const folder = process.argv[2];
fs.readdirSync(folder)
  .filter(file => /IMG_\d{4}\.(JPG|HEIC)$/i.test(file))
  .forEach(async file => {
    const oldName = path.join(folder, file);
    const exifData = await exifr.parse(oldName, ['DateTimeOriginal']);
    // console.log(JSON.stringify(exifData));
    if (!exifData) return;

    const taken = moment(exifData.DateTimeOriginal, 'YYYY:MM:DD HH:mm:ss');
    if (!taken.isValid()) return;

    const newName = taken.format('[IMG]_YYYYMMDD_HHmmss') + path.extname(oldName);
    console.log(file, taken, newName);
    // fs.renameSync(oldName, path.join(folder, newName));
  });

And then comes MOV! Didn’t find metadata for MOV, so let’s stick to the created date.

const util = require('util');
const fs = require('fs');
const path = require('path');
const moment = require('moment');  // npm i moment

const folder = process.argv[2];
fs.readdirSync(folder)
  .filter(file => /IMG_\d{4}\.MOV$/i.test(file))
  .forEach(file => {
    const oldName = path.join(folder, file);
    const taken = moment(fs.statSync(oldName).birthtime);
    if (!taken.isValid()) return;
    const newName = taken.format('[IMG]_YYYYMMDD_HHmmss[.mov]');
    console.log(file, taken, newName);
    // fs.renameSync(oldName, path.join(folder, newName));
  });

It should be easy to merge the scripts if needed.