Skip to content

Instantly share code, notes, and snippets.

@varunnayal
Created November 1, 2017 12:21
Show Gist options
  • Save varunnayal/4dfb35160dbb00bb2a2ceb7c771dafb1 to your computer and use it in GitHub Desktop.
Save varunnayal/4dfb35160dbb00bb2a2ceb7c771dafb1 to your computer and use it in GitHub Desktop.
Get next filename when files are ordered in format <filename>.<integer>
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