輸入一組路徑,轉換成 sprintf format
如把
'D:\\\\workspace\\path-parser\\img\\img_0005.txt'
轉換為
D:\\\\workspace\\path-parser\\img\\img_%04d.txt
基本上就是個掃目錄的蠢方法,反正成功了…演算法如下,後面附上 Javascript code
- 把輸入路徑轉換成 regex (這邊假定是索引最後一組數字字串)
- 在對應目錄下用 regex 找符合的檔名,紀錄最長和最短檔名長度
- 如果長度相同,就是有 zero padding ( e.g. %04d ),反之沒有
- 根據有沒有 zero padding 決定 format 要怎寫
const fs = require('fs');
let path = 'D:\\\\workspace\\path-parser\\img\\img_0005.txt'
let format = getFormat( path );
console.log( format ); // D:\\\\workspace\\path-parser\\img\\img_%04d.txt
function getFormat( path ) {
// read dir to find min & max length of path of matched item
let len = findLength( path );
// split path
let match = parsePath( path );
let format;
if ( len.max == len.min ) { // has zero padding
let digitLen = match[2].match(/\d+(?![\s\S]*\d+)/g)[0].length;
let fileNameRegex = replaceIdx(match[2], `%0${digitLen}d`);
let dir = match[1].replace(/\\/g, '\\\\');
format = dir + fileNameRegex + '.' + match[3];
} else {
let fileNameRegex = replaceIdx(match[2], '%d');
let dir = match[1].replace(/\\/g, '\\\\');
format = dir + fileNameRegex + '.' + match[3];
}
return format;
///////////////////////////////////////////////////////////////
////////////////////private functions//////////////////////////
///////////////////////////////////////////////////////////////
function parsePath( path ) {
let reg = /(.*(?:\\|\/)+)?(.*)\.([^?\s]*)/g
return reg.exec(path);
}
function replaceIdx( fileNameWithoutExt, replaceStr ) {
// return last match with replaced string
return fileNameWithoutExt.replace(/\d+(?![\s\S]*\d+)/g, replaceStr);
}
function pathToRegexStr( path ) {
let match = parsePath( path );
let fileNameRegex = replaceIdx(match[2], '\\d+');
let dir = match[1].replace(/\\/g, '\\\\');
let finalPattern = dir + fileNameRegex + '.' + match[3];
return finalPattern;
}
function findLength( path ) {
let regexPattern = pathToRegexStr( path );
let pathArr = parsePath( path );
let fileList = fs.readdirSync( pathArr[1] );
let minLength = 999999;
let maxLength = 0;
let minLengthFilePath = '';
let maxLengthFilePath = '';
let reg = new RegExp(regexPattern);
// scan all file
for (let i = 0; i < fileList.length; ++i) {
let fullPath = pathArr[1]+fileList[i];
//console.log( 'test: ' + fullPath );
// find match pattern
if ( reg.test( fullPath ) ) {
// update longest path
if ( fullPath.length > maxLength ) {
maxLength = fullPath.length;
maxLengthFilePath = fullPath;
}
// update shortest path
if ( fullPath.length < minLength ) {
minLength = fullPath.length;
minLengthFilePath = fullPath;
}
}
}
return {min: minLength, max: maxLength};
}
}
