diff --git a/finder.mjs b/finder.mjs index 9ae8150..ccc4992 100644 --- a/finder.mjs +++ b/finder.mjs @@ -103,6 +103,15 @@ export default class finder { return listOfTags } + static removeTagInProperties(properties, tagName) { + + let foundTagNameIndex = properties.tags.indexOf(tagName) + if (foundTagNameIndex) { + delete properties.tags[foundTagNameIndex] + } + return properties + } + static cleanSpaces (inputString) { return inputString.trim().replace(/ *g/, ' ') } diff --git a/index.mjs b/index.mjs index 67fcba8..df38529 100644 --- a/index.mjs +++ b/index.mjs @@ -8,221 +8,217 @@ --------------------- */ import fs from 'node-fs' import minimist from 'minimist' -import log from 'loglevel'; -import path from "node:path"; +import log from 'loglevel' +import path from 'node:path' /** --------------------- custom utilities and configuration --------------------- */ import rangement_instance from './configs.mjs' import { - TestFindFormattedDate, - TestScreenShotIsFoundAndRenamed, - TestTagsAreDetectedInFileName + TestFindFormattedDate, + TestScreenShotIsFoundAndRenamed, + TestTagsAreDetectedInFileName } from './testFunctions.mjs' import finder from './finder.mjs' -import exiftool from "node-exiftool"; - let mini_arguments log.setLevel(rangement_instance.log_level) log.info(' ') -function parseArguments() { - mini_arguments = minimist(process.argv.slice(2)) - log.debug('arguments', mini_arguments) +function parseArguments () { + mini_arguments = minimist(process.argv.slice(2)) + log.debug('arguments', mini_arguments) } -function addOriginalFileNameIfMissing(originalFileName, fileMixedNewName) { +function addOriginalFileNameIfMissing (originalFileName, fileMixedNewName) { - // const ep = new exiftool.ExiftoolProcess() - // - // ep - // .open(fileMixedNewName) - // .then(() => ep.writeMetadata(fileMixedNewName, { - // 'OriginalFileName+': originalFileName, - // })) - // .then(console.log, console.error) - // .then(() => ep.close()) - // .catch(console.error) + // const ep = new exiftool.ExiftoolProcess() + // + // ep + // .open(fileMixedNewName) + // .then(() => ep.writeMetadata(fileMixedNewName, { + // 'OriginalFileName+': originalFileName, + // })) + // .then(console.log, console.error) + // .then(() => ep.close()) + // .catch(console.error) } -function renameFile(originalFileName, fileMixedNewName) { - fs.rename(originalFileName, fileMixedNewName, function (err) { - log.info('name changed', fileMixedNewName) - if (err) { - log.info('rename ERROR: ' + err) - } else { - // otherRenames.push(originalFileName) - otherRenames.push(fileMixedNewName) +function renameFile (originalFileName, fileMixedNewName) { + fs.rename(originalFileName, fileMixedNewName, function (err) { + log.info('name changed', fileMixedNewName) + if (err) { + log.info('rename ERROR: ' + err) + } else { + // otherRenames.push(originalFileName) + otherRenames.push(fileMixedNewName) - addOriginalFileNameIfMissing(originalFileName, fileMixedNewName) - // rangement_instance.statistics['filesModified']++ - } - }) -} -function makeFileNameFromProperties(fileProperties) { - - let tagPlace = '' - log.info('fileProperties.tags',fileProperties.tags) - if (fileProperties.tags.length && rangement_instance.keepTags) { - tagPlace = ' ' + rangement_instance.tagSectionSeparator + ' '+ fileProperties.tags.join(rangement_instance.tagSeparator) - } - console.log('fileProperties.dateStampExif', fileProperties.dateStampExif) - let newName = '' - + fileProperties.dateStampExif - + ' ' - + (rangement_instance.keepFreeText? fileProperties.freeText : '') - + tagPlace - + fileProperties.extension; - - if(rangement_instance.replaceUnderscoreWithSpaces){ - newName = newName.replace('_', ' ') - } - - newName = newName.replace(' ', '') - - return newName + addOriginalFileNameIfMissing(originalFileName, fileMixedNewName) + // rangement_instance.statistics['filesModified']++ + } + }) } -let otherRenames = []; +export function makeFileNameFromProperties (fileProperties) { -function shouldWeChangeName(structureForFile) { - log.info(' ______ shouldWeChangeName ', structureForFile.fileNameOriginal) - let newName = makeFileNameFromProperties(structureForFile) - log.debug('newName', newName) - if (structureForFile.fileNameOriginal !== newName && !otherRenames.includes(newName)) { + let tagPlace = '' + log.info('fileProperties.tags', fileProperties.tags) + if (fileProperties.tags.length && rangement_instance.keepTags) { + tagPlace = ' ' + rangement_instance.tagSectionSeparator + ' ' + fileProperties.tags.join(rangement_instance.tagSeparator) + } + console.log('fileProperties.dateStampExif', fileProperties.dateStampExif) + let newName = '' + + fileProperties.dateStampExif + + ' ' + + (rangement_instance.keepFreeText ? fileProperties.freeText : '') + + tagPlace + + fileProperties.extension - log.info('\n ancien nom :', structureForFile.fileNameOriginal) + if (rangement_instance.replaceUnderscoreWithSpaces) { + newName = newName.replace('_', ' ') + } - log.info(' nouveau nom:', newName) - if (!mini_arguments['dry-run']) { - renameFile(structureForFile.fullPath, structureForFile.folderPath + newName) - } else { - log.info('no renaming for real, this is a dry run') - } - } else { - log.info(' rien à changer') - } + newName = finder.cleanSpaces(newName) + + return newName } +let otherRenames = [] + +function shouldWeChangeName (structureForFile) { + log.info(' ______ shouldWeChangeName ', structureForFile.fileNameOriginal) + let newName = makeFileNameFromProperties(structureForFile) + log.debug('newName', newName) + if (structureForFile.fileNameOriginal !== newName && !otherRenames.includes(newName)) { + + log.info('\n ancien nom :', structureForFile.fileNameOriginal) + + log.info(' nouveau nom:', newName) + if (!mini_arguments['dry-run']) { + renameFile(structureForFile.fullPath, structureForFile.folderPath + newName) + } else { + log.info('no renaming for real, this is a dry run') + } + } else { + log.info(' rien à changer') + } +} + + /** * guess file name on one file which is not a directory * @param fullPath */ -function guessFileNameOnOnefile(fullPath) { +function guessFileNameOnOnefile (fullPath) { - log.info('go guess file name on file: ', fullPath ) - fs.stat(fullPath, (err, stats) => { + log.info('go guess file name on file: ', fullPath) + fs.stat(fullPath, (err, stats) => { - if (err) { - log.error('échec fichier', err) - log.error('ce fichier n existe pas: ', fullPath) - return; - } else { + if (err) { + log.error('échec fichier', err) + log.error('ce fichier n existe pas: ', fullPath) + return + } else { - let structureForFile = finder.destructurateFileName(fullPath) + let structureForFile = finder.destructurateFileName(fullPath) - // examiner les infos exif de chaque fichier pour proposer un nouveau nom - if (!structureForFile.dateStampInFileNameOriginal) { - log.info(' le nom de fichier "'+structureForFile.freeText +'" ne contient pas de date formatée au début') + // examiner les infos exif de chaque fichier pour proposer un nouveau nom + if (!structureForFile.dateStampInFileNameOriginal) { + log.info(' le nom de fichier "' + structureForFile.freeText + '" ne contient pas de date formatée au début') - finder.findExifCreationDate(structureForFile.fullPath) - .then(data => { - log.info(' ... chercher la date de création : "'+structureForFile.freeText +'"') - let foundDate = finder.findEarliestDateInExifData(data) + finder.findExifCreationDate(structureForFile.fullPath) + .then(data => { + log.info(' ... chercher la date de création : "' + structureForFile.freeText + '"') + let foundDate = finder.findEarliestDateInExifData(data) - log.info(' =>>>>>>> foundDate : ', foundDate) - if (foundDate) { - structureForFile.dateStampExif = foundDate - } else { - log.info('pas de date trouvée dans le nom') - } - shouldWeChangeName(structureForFile) - } - , - (error) => { - log.warn('/////////// Error in reading exif of file: ' + error.message) - return '' - }) - } + log.info(' =>>>>>>> foundDate : ', foundDate) + if (foundDate) { + structureForFile.dateStampExif = foundDate + } else { + log.info('pas de date trouvée dans le nom') + } + shouldWeChangeName(structureForFile) + } + , + (error) => { + log.warn('/////////// Error in reading exif of file: ' + error.message) + return '' + }) + } - } - }) + } + }) } let expandedFileList = [] -let cwd = path.dirname(process.cwd()) + '/' + path.basename(process.cwd()); +let cwd = path.dirname(process.cwd()) + '/' + path.basename(process.cwd()) console.log('cwd', cwd) -function guessFileNameOnAllFilesFromArguments() { +function guessFileNameOnAllFilesFromArguments () { + // parcourir les fichiers + log.debug('liste des fichiers', mini_arguments._) + let fileList = mini_arguments._ - // parcourir les fichiers - log.debug('liste des fichiers', mini_arguments._) - let fileList = mini_arguments._ + // test file exists + fileList.forEach(fullPath => { + // parcourir les dossiers + isFolderOrFile(`${fullPath}`) + } + ) - - // test file exists - fileList.forEach(fullPath => { - // parcourir les dossiers - isFolderOrFile(`${fullPath}`) - } - ) - - log.info('expanded file list :', expandedFileList) - expandedFileList.forEach(filePath => guessFileNameOnOnefile(filePath)) + log.info('expanded file list :', expandedFileList) + expandedFileList.forEach(filePath => guessFileNameOnOnefile(filePath)) } -function readSubdirectories(baseDir) { - const newGlob = baseDir; - fs.readdir(baseDir, (err, files) => { - if (err) throw err; +function readSubdirectories (baseDir) { + const newGlob = baseDir + fs.readdir(baseDir, (err, files) => { + if (err) throw err - console.log('readSubdirectories - files', files) - files.forEach((subDirOrFile) => { - const newFullPath = cwd +'/'+ subDirOrFile; + console.log('readSubdirectories - files', files) + files.forEach((subDirOrFile) => { + const newFullPath = cwd + '/' + subDirOrFile - if (fs.existsSync(newFullPath)) { - const s = fs.statSync(newFullPath); + if (fs.existsSync(newFullPath)) { + const s = fs.statSync(newFullPath) - if (s.isFile()) { - expandedFileList.push(cwd+'/'+subDirOrFile) - } - } - }); - }); + if (s.isFile()) { + expandedFileList.push(cwd + '/' + subDirOrFile) + } + } + }) + }) } -function isFolderOrFile(fileName) { - // const stat = fs.statSync(cwd + '/' + fileName); - const stat = fs.statSync( fileName); +function isFolderOrFile (fileName) { + // const stat = fs.statSync(cwd + '/' + fileName); + const stat = fs.statSync(fileName) - if (stat.isDirectory()) { - let fileList = readSubdirectories(fileName); - console.log('fileList in directory ',fileName, '\n', fileList) - if (fileList) { - expandedFileList.push(...fileList) - } - } - else if (stat.isFile()) { - expandedFileList.push(cwd + '/' + fileName) - } + if (stat.isDirectory()) { + let fileList = readSubdirectories(fileName) + console.log('fileList in directory ', fileName, '\n', fileList) + if (fileList) { + expandedFileList.push(...fileList) + } + } else if (stat.isFile()) { + expandedFileList.push(cwd + '/' + fileName) + } } parseArguments() guessFileNameOnAllFilesFromArguments() - // run tests if (rangement_instance.enableTestsLocally) { - TestTagsAreDetectedInFileName() - TestFindFormattedDate() - TestScreenShotIsFoundAndRenamed() + TestTagsAreDetectedInFileName() + TestFindFormattedDate() + TestScreenShotIsFoundAndRenamed() } if (rangement_instance.reportStatistics || mini_arguments.stats) { - finder.reportStatistics() + finder.reportStatistics() } diff --git a/tests/finder.test.js b/tests/finder.test.js index f8546ac..6cac0c1 100644 --- a/tests/finder.test.js +++ b/tests/finder.test.js @@ -1,4 +1,6 @@ import finder from '../finder.mjs' +import { makeFileNameFromProperties } from '../index' +import { expect } from '@jest/globals' describe('detection in file name', () => { @@ -52,21 +54,69 @@ describe('modification in file name', () => { ) .toBe('mon texte ajouté à la fin du texte libre') }) - xtest('should replace text in file name', () => { - + test('should replace text in file name', () => { + let searchString = 'vacances', replaceString = 'machin' + let replacedString = finder.searchAndReplaceInFileName(searchString, replaceString, fileNameOriginal) + expect( + replacedString + ) + .toBe('mon texte -- famille machin plage.jpg') }) }) -xdescribe('modifications with tags', () => { +describe('modifications with tags', () => { - xtest('should add tag in file name', () => { + let fileNameOriginal = 'mon nom sans aucun tag.jpg' + let properties = finder.destructurateFileName(fileNameOriginal) + + test('should have no tag in file properties', () => { + expect( + properties.tags + ) + .toStrictEqual([]) }) - xtest('should remove tag in file name', () => { + test('should list existing tags in file name', () => { + let fileNameOriginal = 'mon nom -- carte bidule.jpg' + let otherProperties = finder.destructurateFileName(fileNameOriginal) + + expect( + otherProperties.tags + ) + .toStrictEqual(['carte','bidule']) }) - xtest('should remove and add tags in file name', () => { + test('should add tag in file name', () => { + + let newTag = 'illustration' + let newName = finder.addTagInFileName(newTag, fileNameOriginal) + + expect(newName) + .toBe('mon nom sans aucun tag -- illustration.jpg') + + let otherProperties = finder.destructurateFileName(newName) + expect( + otherProperties.tags + ) + .toStrictEqual(['illustration']) + + expect( + makeFileNameFromProperties(otherProperties) + ) + .toBe('mon nom sans aucun tag -- illustration.jpg') + }) + test('should remove tag in file name', () => { + + let fileNameOriginal = 'mon nom avec un tag -- voyages.jpg' + // let properties = finder.destructurateFileName(fileNameOriginal) + // expect(properties.tags).toStrictEqual(['voyages']) + + let newProperties = finder.removeTagInProperties(properties, 'voyages') + expect(newProperties.tags).toStrictEqual([]) + }) + + xtest('should remove with minus prefix and add tags in file name at the same time', () => { }) }) \ No newline at end of file