Created
November 1, 2017 12:21
-
-
Save varunnayal/4dfb35160dbb00bb2a2ceb7c771dafb1 to your computer and use it in GitHub Desktop.
Get next filename when files are ordered in format <filename>.<integer>
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const RegExp_escape = function(s) { | |
return (s ? s + '' : '').replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'); | |
}; | |
/** | |
* @prop {Object} options - Options Object or String if Filename | |
* @param {String} filename - File name | |
* @param {String} dir - Directory to look for filename pattern | |
* @param {String} max_files - Max files you want to create. Non positive means unlimited | |
*/ | |
function FileNextInteger(options) { | |
if ( !options || !options.filename || !options.dir) { | |
throw new Error('Filename and dir required') | |
} | |
this.filename = options.filename.toString(); | |
this.dir = options.dir.toString(); | |
this.delimeter = '.'; | |
this.max_files = parseInt(options.max_files, 10) || 0; | |
} | |
// FileNextInteger.prototype. = function() { } | |
FileNextInteger.prototype._generateFileName = function(index) { | |
if (index) { | |
return this.filename + this.delimeter + index; | |
} | |
return this.filename; | |
} | |
FileNextInteger.prototype._getRegexString = function() { | |
return '^' + RegExp_escape(this.filename) + '(' + RegExp_escape(this.delimeter) + '\\d+)?$'; | |
} | |
FileNextInteger.prototype.getNext = function() { | |
var regex = new RegExp(this._getRegexString()); | |
var self = this; | |
var maxUsedNum = -1; | |
var files = fs.readdirSync(this.dir).every(function(file) { | |
result = regex.exec(file); | |
// No match | |
if (result === null) { | |
return true; | |
} | |
// Consider example: | |
// A) filename: 'a.log.12' | |
// - result = [ 'a.log.12', '.12' ] | |
// - numberStr = '.12' | |
// - number = '.12'.substring('.'.length) = '12' | |
// B) filename: 'a.log' | |
// - result = [ 'a.log.12', undefined ] // undefined as no group match | |
// - numberStr = undefined | |
// - number = 0 | |
var number = -1; | |
if (!result[result.length - 1]) { | |
number = 0; | |
} else { | |
number = parseInt(result[result.length - 1].substring(self.delimeter.length), 10); | |
} | |
if (number > maxUsedNum) { | |
maxUsedNum = number; | |
} | |
if (self.max_files && self.max_files <= maxUsedNum) { | |
return false; | |
} | |
return true; | |
}); | |
// Maximum files used | |
if (self.max_files && self.max_files <= maxUsedNum) { | |
return null; | |
} | |
// No file present | |
if (maxUsedNum < 0) { | |
return this._generateFileName(); | |
} | |
return this._generateFileName(maxUsedNum + 1); | |
} | |
/** | |
* For files under directory say '/tmp/abc', we have following files: | |
* - a.log | |
* - a.log.1 | |
* - a.log.2 | |
* - other.log | |
* - other.log.1 | |
* | |
* require('./file-next-integer')({ | |
* dir: '/tmp/abc', | |
* filename: 'a.log', | |
* }).getNext() | |
* | |
* Above script will return filename as 'a.log.3' | |
* | |
*/ | |
module.exports = function(options) { | |
return new FileNextInteger(options); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment