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.