I am trying to re-organise my mp3 collection based on its id3 meta data into folders based on the artist. I'm new to nodeJs and more importantly promises. I was hoping I could get some feedback on my script. I can manage the creating of folders and copying of files quite easily, but I'm a little unsure on the async reading and looping part (shown below).
It does run, but almost crashes my computer when I run it on the full directory.
Thanks in advance for any suggestions or advice.
const fs = require('fs');
const NodeID3 = require('node-id3-promise')
const util = require("util");
const testFolder = '/home/james/Music';
const reorderedFolder = '/home/james/Music/reordered';
const existsProm = util.promisify(fs.access);
const statsProm = util.promisify(fs.stat);
const mkdirProm = util.promisify(fs.mkdir);
const copyFileProm = util.promisify(fs.copyFile);
const removeFileProm = util.promisify(fs.rm);
const readAllFiles = util.promisify(fs.readdir);
const isDelete = false;
async function getFiles(){
const files = await readAllFiles(testFolder);
return Promise.all(files);
}
(async ()=>{
const files = await getFiles();
files.forEach(file => {
var sourceFilePath = testFolder + "/" + file;
Promise.resolve(sourceFilePath)
.then(filePath =>{
//Return an array of promises. a) does file exist, b) filePath
return Promise.all([existsProm(filePath), Promise.resolve(filePath)]);
})
.catch(err =>{
//File wasn't found. Kill it.
throw new Error("File not found");
})
.then(fileExistsAndFilePath => {
//get tags for existing file path.
return Promise.all([NodeID3.read(fileExistsAndFilePath[1]), fileExistsAndFilePath[1]])
})
.then(tagAndFilePath => {
//get the id3 tag info and create an object from it.
var tagDetails = {};
tagDetails.artist = tagAndFilePath[0].artist;
tagDetails.title = tagAndFilePath[0].title;
tagDetails.filePath = tagAndFilePath[1];
return tagDetails;
})
.then(tagDetails => {
//Create file paths
if(tagDetails != null && tagDetails.artist != null && tagDetails.title != null){
var fileAndFolder = {};
fileAndFolder.existingFilePath = tagDetails.filePath;
fileAndFolder.newFolderPath = reorderedFolder + "/" + tagDetails.artist;
fileAndFolder.newFilePath = fileAndFolder.newFolderPath + "/" + tagDetails.title + ".mp3";
return fileAndFolder;
}else{
throw new Error("No artist");
}
})
.then(fileAndFolder => {
//Create the directory, if it exists, ignore the error
return Promise.all([mkdirProm(fileAndFolder.newFolderPath).catch(err => {}), fileAndFolder]);
})
.then(mdkirAndFileAndFolder => {
//Copy the file to the new location
return Promise.all([
copyFileProm(mdkirAndFileAndFolder[1].existingFilePath, mdkirAndFileAndFolder[1].newFilePath).catch(err => {
console.log(err);
throw new Error("Problem copying file");
}),
mdkirAndFileAndFolder[1]
]);
})
.then(copyFileResultAndFileAndFolder => {
//Remove the old file
if(isDelete){
return Promise.all([
removeFileProm(copyFileResultAndFileAndFolder[1].existingFilePath).catch(err => {console.log("Problem deleting file " + err);}),
copyFileResultAndFileAndFolder[1].existingFilePath
]);
}else{
return Promise.all([null, copyFileResultAndFileAndFolder[1].existingFilePath]);
}
})
.then(rmFileResult => {
//Output success message
console.log(rmFileResult[1] + " = successfully moved.");
return true;
})
.catch(error => {
if(error.message != "File not found" && error.message != "No artist"){
console.error(error);
}
})
});
})()