google-photos-migrate
Version:
A tool to fix EXIF data and recover filenames from a Google Photos takeout.
47 lines (46 loc) • 1.63 kB
JavaScript
import { move, pathExists } from 'fs-extra';
import { copyFile, mkdir } from 'fs/promises';
import { basename, resolve } from 'path';
import sanitize from 'sanitize-filename';
async function _saveToDir(file, destDir, saveBase, doMove = false, duplicateIndex = 0) {
const saveDir = resolve(destDir, duplicateIndex > 0 ? `duplicates-${duplicateIndex}` : '.');
await mkdir(saveDir, { recursive: true });
const savePath = resolve(saveDir, saveBase);
const exists = await pathExists(savePath);
if (exists) {
return _saveToDir(file, destDir, saveBase, doMove, duplicateIndex + 1);
}
if (doMove) {
await move(file, savePath);
}
else {
await copyFile(file, savePath);
}
return savePath;
}
/** Copies or moves a file to dir, saves duplicates in subfolders and returns the new path.
* Atomic within this app, sanitizes filenames.
*/
export async function saveToDir(file, destDir, migCtx, move = false, saveBase) {
saveBase = saveBase ?? basename(file);
let sanitized = sanitize(saveBase, { replacement: '_' });
if (sanitized === '') {
sanitized = migCtx.renameEmpty;
}
if (saveBase != sanitized) {
migCtx.warnLog(`Sanitized file: ${file}` + ` (New filename: ${sanitized})`);
}
const lcBase = saveBase.toLowerCase();
let lock;
while ((lock = migCtx.migrationLocks.get(lcBase))) {
await lock;
}
lock = _saveToDir(file, destDir, sanitized, move);
migCtx.migrationLocks.set(lcBase, lock);
try {
return await lock;
}
finally {
migCtx.migrationLocks.delete(lcBase);
}
}