dir-parser
Advanced tools
+40
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| function calcSizekb(size){ | ||
| return `${Math.round((size / 1024) * 100) / 100}kb`; | ||
| } | ||
| exports.DirInfo = class DirInfo { | ||
| constructor(name, dirPath) { | ||
| this.name = name; | ||
| this.type = 'directory'; | ||
| this.size = 0; | ||
| this.size_kb = 0; | ||
| this.path = dirPath; | ||
| this.absPath = path.resolve(dirPath); | ||
| this.dir = path.dirname(dirPath); | ||
| this.absDir = path.dirname(this.absPath); | ||
| this.dirNum = 0; | ||
| this.fileNum = 0; | ||
| this.members = []; | ||
| } | ||
| } | ||
| exports.FileInfo = class FileInfo { | ||
| constructor (name, filePath) { | ||
| const infos = path.parse(filePath); | ||
| this.name = name; | ||
| this.base = infos.name; | ||
| this.ext = infos.ext; | ||
| this.type = 'file'; | ||
| this.size = fs.statSync(filePath).size; | ||
| this.size_kb = calcSizekb(this.size); | ||
| this.path = filePath; | ||
| this.absPath = path.resolve(filePath); | ||
| this.dir = infos.dir; | ||
| this.absDir = path.dirname(this.absPath); | ||
| } | ||
| } | ||
| exports.calcSizekb = calcSizekb; |
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| const { DirInfo, FileInfo, calcSizekb } = require('./base'); | ||
| /** | ||
| * Parse the target directory and generate it's structure tree. | ||
| * @param target string | ||
| * @param options object | ||
| */ | ||
| module.exports = function (target, options = {}) { | ||
| if (!fs.statSync(target).isDirectory()) { | ||
| throw new Error('Target must be a directory!') | ||
| } | ||
| let isGetDirTree = typeof options.dirTree === 'boolean' ? options.tree : true; | ||
| const isGetMembers = !!options.members; | ||
| const isGetFiles = !!options.files; | ||
| const noNum = !!options.noNum; | ||
| const absTarget = path.resolve(target); | ||
| const tarName = path.basename(absTarget) | ||
| const excludes = options.excludes || []; | ||
| const exdPaths = (options.exdPaths || []).map(ex => path.resolve(ex)); | ||
| const tarInfo = new DirInfo(tarName, target); | ||
| let dirTree = ''; | ||
| const dirs = []; | ||
| const files = []; | ||
| if (isGetMembers) { | ||
| dirs.push({ | ||
| 'path': target, | ||
| 'info': tarInfo | ||
| }); | ||
| } | ||
| /** | ||
| * Parser The target directory | ||
| * @param dirPath string | ||
| * @param deep deep = 1 | ||
| * @param prev prev = '' | ||
| */ | ||
| function parseDir(dirPath, members, deep = 1, prev = '') { | ||
| const subDirs = []; | ||
| const subFiles = []; | ||
| let filesSize = 0; | ||
| // Classify directorys and files of the dirPath | ||
| fs.readdirSync(dirPath).forEach(item => { | ||
| const iPath = path.join(dirPath, item); | ||
| const isExdPath = exdPaths.some(ePath => iPath === ePath); | ||
| if (!isExdPath && !excludes.includes(item)) { | ||
| const stat = fs.statSync(iPath); | ||
| const memberInfo = { | ||
| 'name': item, | ||
| 'path': iPath | ||
| }; | ||
| if (stat.isDirectory()) { | ||
| subDirs.push(memberInfo); | ||
| } else if (stat.isFile()) { | ||
| subFiles.push(memberInfo); | ||
| } | ||
| } | ||
| }); | ||
| // handle directorys | ||
| let split = ''; | ||
| let dirInfo = {}; | ||
| subDirs.forEach((dir, i) => { | ||
| if (isGetMembers) { | ||
| dirInfo = new DirInfo(dir.name, dir.path); | ||
| dirs.push({ | ||
| 'path': dirInfo.path, | ||
| 'info': dirInfo | ||
| }); | ||
| members.push(dirInfo); | ||
| } | ||
| if (isGetDirTree) { | ||
| if (i < subDirs.length - 1 || subFiles.length > 0) { | ||
| dirTree += `${prev} ├─ ${dir.name}\r\n`; | ||
| split = ' │'; | ||
| } else { | ||
| dirTree += `${prev} └─ ${dir.name}\r\n`; | ||
| split = ' '; | ||
| } | ||
| } | ||
| const nextPath = path.join(dirPath, dir.name); | ||
| const nextMemb = isGetMembers ? dirInfo.members : members; | ||
| const nextDeep = deep + 1; | ||
| const nextSplit = prev + split; | ||
| parseDir(nextPath, nextMemb, nextDeep, nextSplit); | ||
| }); | ||
| // Handle files | ||
| subFiles.forEach((file, i) => { | ||
| if (isGetMembers || isGetFiles) { | ||
| const fileInfo = new FileInfo(file.name, file.path); | ||
| if (isGetFiles) { | ||
| files.push(fileInfo); | ||
| } | ||
| if (isGetMembers) { | ||
| members.push(fileInfo); | ||
| } | ||
| filesSize += fileInfo.size; | ||
| } | ||
| if (isGetDirTree) { | ||
| if (i < subFiles.length - 1) { | ||
| dirTree += `${prev} ├─ ${file.name}\r\n`; | ||
| } else { | ||
| dirTree += `${prev} └─ ${file.name}\r\n`; | ||
| } | ||
| } | ||
| }); | ||
| if (isGetMembers) { | ||
| dirs.forEach(dir => { | ||
| if (dirPath.includes(dir.path)) { | ||
| dir.info.dirNum += subDirs.length; | ||
| dir.info.fileNum += subFiles.length; | ||
| dir.info.size += filesSize; | ||
| dir.info.size_kb = calcSizekb(dir.info.size); | ||
| } | ||
| }); | ||
| } else { | ||
| tarInfo.dirNum += subDirs.length; | ||
| tarInfo.fileNum += subFiles.length; | ||
| } | ||
| } | ||
| parseDir(target, tarInfo.members); | ||
| if (!isGetMembers) { | ||
| delete tarInfo.members; | ||
| if (!isGetFiles) { | ||
| delete tarInfo.size; | ||
| delete tarInfo.size_kb; | ||
| } | ||
| } | ||
| if (isGetFiles) { | ||
| tarInfo.files = files; | ||
| tarInfo.size = files.reduce((size, file) => size + file.size, tarInfo.size); | ||
| tarInfo.size_kb = calcSizekb(tarInfo.size); | ||
| } | ||
| if (isGetDirTree) { | ||
| if (noNum) { | ||
| dirTree = `${tarName}\r\n${dirTree}`; | ||
| } else { | ||
| dirTree = `${tarName} ( Directorys: ${tarInfo.dirNum}, Files: ${tarInfo.fileNum} )\r\n${dirTree}`; | ||
| } | ||
| tarInfo.dirTree = dirTree.replace(/\r\n$/, ''); | ||
| } | ||
| return tarInfo; | ||
| } | ||
+1
-1
@@ -8,3 +8,3 @@ #!/usr/bin/env node | ||
| const package = require('../package.json'); | ||
| const parse = require('../index'); | ||
| const parse = require('../src/dir-parser'); | ||
@@ -11,0 +11,0 @@ const dirInfoFile = 'dir-info.txt'; |
+4
-1
@@ -1,2 +0,2 @@ | ||
| dir-parser ( Directorys: 7, Files: 28 ) | ||
| dir-parser ( Directorys: 8, Files: 30 ) | ||
| ├─ bin | ||
@@ -30,2 +30,5 @@ │ └─ parser.js | ||
| │ └─ Readme.md | ||
| ├─ src | ||
| │ ├─ base.js | ||
| │ └─ dir-parser.js | ||
| ├─ .gitignore | ||
@@ -32,0 +35,0 @@ ├─ dir-parser.png |
+1
-92
@@ -1,92 +0,1 @@ | ||
| #!/usr/bin/env node | ||
| const fs = require('fs'); | ||
| const path = require('path'); | ||
| /** | ||
| * Parse the target directory and generate it's structure tree. | ||
| * @param target string | ||
| * @param options object | ||
| */ | ||
| module.exports = function (target, options = {}) { | ||
| if (!fs.statSync(target).isDirectory()) { | ||
| throw new Error('Target must be a directory!') | ||
| } | ||
| let fileNum = 0; | ||
| let dirNum = 0; | ||
| let dirTree = ''; | ||
| const noNum = options.noNum || false; | ||
| const dirName = path.basename(path.resolve(target)) | ||
| const excludes = options.excludes || []; | ||
| const exdPaths = (options.exdPaths || []).map(ex => path.resolve(ex)); | ||
| /** | ||
| * Parser The target directory | ||
| * @param dirPath string | ||
| * @param deep deep = 1 | ||
| * @param prev prev = '' | ||
| */ | ||
| function parseDir(dirPath, deep = 1, prev = '') { | ||
| const subDirs = []; | ||
| const subFiles = []; | ||
| // Classify directorys and files of the dirPath | ||
| fs.readdirSync(dirPath).forEach(item => { | ||
| const itPath = path.join(dirPath, item); | ||
| const isExdPath = exdPaths.some(ePath => itPath === ePath); | ||
| if (!isExdPath && !excludes.includes(item)) { | ||
| const stat = fs.statSync(itPath); | ||
| if (stat.isDirectory()) { | ||
| subDirs.push(item); | ||
| } else if (stat.isFile()) { | ||
| subFiles.push(item); | ||
| } | ||
| } | ||
| }); | ||
| dirNum += subDirs.length; | ||
| fileNum += subFiles.length; | ||
| // handle directorys | ||
| let split = ''; | ||
| subDirs.forEach((dir, i) => { | ||
| if (i < subDirs.length - 1 || subFiles.length > 0) { | ||
| dirTree += `${prev} ├─ ${dir}\r\n`; | ||
| split = ' │'; | ||
| } else { | ||
| dirTree += `${prev} └─ ${dir}\r\n`; | ||
| split = ' '; | ||
| } | ||
| const nextPath = path.join(dirPath, dir); | ||
| const nextDeep = deep + 1; | ||
| const nextSplit = prev + split; | ||
| parseDir(nextPath, nextDeep, nextSplit); | ||
| }); | ||
| // Handle files | ||
| subFiles.forEach((file, i) => { | ||
| if (i < subFiles.length - 1) { | ||
| dirTree += `${prev} ├─ ${file}\r\n`; | ||
| } else { | ||
| dirTree += `${prev} └─ ${file}\r\n`; | ||
| } | ||
| }); | ||
| } | ||
| parseDir(target); | ||
| if (noNum) { | ||
| dirTree = `${dirName}\r\n${dirTree}`; | ||
| } else { | ||
| dirTree = `${dirName} ( Directorys: ${dirNum}, Files: ${fileNum} )\r\n${dirTree}`; | ||
| } | ||
| return { | ||
| 'fileNum': fileNum, | ||
| 'dirNum': dirNum, | ||
| 'dirName': dirName, | ||
| 'dirTree': dirTree.replace(/\r\n$/, '') | ||
| } | ||
| } | ||
| module.exports = require('./src/dir-parser'); |
+1
-1
| { | ||
| "name": "dir-parser", | ||
| "version": "1.0.7", | ||
| "version": "1.0.8", | ||
| "description": "Parse a directory and generate it's structure tree.", | ||
@@ -5,0 +5,0 @@ "main": "index.js", |
+63
-38
@@ -8,11 +8,13 @@ # Dir Parser | ||
| ### Demo Image | ||
|  | ||
| ### Install dir-parser | ||
| ``` | ||
| $ npm install dir-parser -g | ||
| ``` | ||
| > $ npm install dir-parser | ||
| ### Get help | ||
| > $ parse -h | ||
| ``` | ||
| $ parse -h | ||
| Usage: index [options] | ||
@@ -31,7 +33,9 @@ Options: | ||
| ``` | ||
| ### Parse your dir | ||
| > $ cd your/demo/app | ||
| > $ parse | ||
| ``` | ||
| $ cd your/demo/app | ||
| $ parse # Terminal log: | ||
| app ( Directorys: 7, Files: 9 ) | ||
@@ -56,6 +60,7 @@ ├─ bin | ||
| ### Parse your dir with params | ||
| > $ parse -e bin,public -n -s | ||
| > $ cat dir-info.txt | ||
| ``` | ||
| $ parse -e bin,public -n -s | ||
| $ cat dir-info.txt | ||
| app | ||
@@ -72,15 +77,17 @@ ├─ routes | ||
| ``` | ||
| ### Recommend usages | ||
| ``` | ||
| # Usage 01 | ||
| #Hint: There should no white space in the excludes series! | ||
| $ parse -e .git,node_modules -x bin/www | ||
| # Usage 01 | ||
| #Hint: There should no white space in the excludes Array! | ||
| $ parse -e ['.git','node_modules'] -x ['bin/www'] | ||
| Usage 01 | ||
| *There should no white space in the excludes series!* | ||
| > $ parse -e .git,node_modules -x bin/www | ||
| # Usage 03 | ||
| # Parse by a config file, In parser.json: | ||
| Usage 02 | ||
| *There should no white space in the excludes Array!* | ||
| > $ parse -e ['.git','node_modules'] -x ['bin/www'] | ||
| Usage 03 | ||
| *Parse by a config file* | ||
| > $ vi parser.conf.json | ||
| ``` | ||
| { | ||
@@ -94,38 +101,53 @@ "directory": "your/demo/app", | ||
| } | ||
| ``` | ||
| > $ parse -c ./parser.conf.json | ||
| $ parse -c ./parser.json | ||
| ``` | ||
| ### In javaScript code | ||
| > $ npm install dir-parse funclib | ||
| > $ vi test.js | ||
| ``` | ||
| $ npm install dir-parse funclib | ||
| $ vi test.js | ||
| const parse = require('dir-parse'); | ||
| const fn = require('funclib'); | ||
| const parse = require('./index'); | ||
| const target = './'; | ||
| const excludes = [ '.git', 'node_modules' ]; | ||
| const excludes = ['.git']; | ||
| const parsed = parse(target, { 'excludes': excludes }); | ||
| const parsedInfo = fn.pick(parsed, [ 'dirName', 'dirNum', 'fileNum' ]); | ||
| const parsed = parse(target, { | ||
| excludes: excludes, | ||
| // dirTree: false, // Default is true, returns will conatins a string of directory structure truee; | ||
| // files: true, // Default is false, If true, parsed will conatins an array of all subfiles's info; | ||
| // members: true // Default is false, If true, parsed will conatins an object of all members's info; | ||
| }); | ||
| fn.log(parsedInfo, '# Parsed Info', { isShowTime: false }); | ||
| fn.log(parsed.dirTree, '# Parsed Dir Tree', { isShowTime: false }); | ||
| const BaseInfo = fn.pick(parsed, prop => !['members', 'files', 'dirTree'].includes(prop)); | ||
| $ node test.js | ||
| fn.log(BaseInfo, '# Parsed Info'); | ||
| fn.log(parsed.dirTree, '# Parsed Dir Tree'); | ||
| // fn.log(parsed.files, '# Parsed Dir Files'); | ||
| // fn.log(parsed.members, '# Parsed Dir Members'); | ||
| ``` | ||
| > $ node test.js | ||
| ``` | ||
| ================================================================== | ||
| # Parsed Info | ||
| [22:10:07] # Parsed Info | ||
| ------------------------------------------------------------------ | ||
| { | ||
| "dirName": "dir-parser", | ||
| "dirNum": 7, | ||
| "fileNum": 29 | ||
| "name": "dir-parser", | ||
| "type": "directory", | ||
| "path": "./", | ||
| "absPath": "E:\\Code\\dir-parser", | ||
| "dir": ".", | ||
| "absDir": "E:\\Code", | ||
| "dirNum": 8, | ||
| "fileNum": 31 | ||
| } | ||
| ================================================================== | ||
| ================================================================== | ||
| # Parsed Dir Tree | ||
| [22:10:07] # Parsed Dir Tree | ||
| ------------------------------------------------------------------ | ||
| dir-parser ( Directorys: 7, Files: 29 ) | ||
| dir-parser ( Directorys: 8, Files: 31 ) | ||
| ├─ bin | ||
@@ -159,2 +181,5 @@ │ └─ parser.js | ||
| │ └─ Readme.md | ||
| ├─ src | ||
| │ ├─ base.js | ||
| │ └─ dir-parser.js | ||
| ├─ .gitignore | ||
@@ -161,0 +186,0 @@ ├─ dir-info.txt |
+13
-3
@@ -7,5 +7,15 @@ const fn = require('funclib'); | ||
| const parsed = parse(target, { 'excludes': excludes }); | ||
| const parsed = parse(target, { | ||
| excludes: excludes, | ||
| // dirTree: false, | ||
| // files: true, | ||
| // members: true | ||
| }); | ||
| fn.log(fn.pick(parsed, ['dirName', 'dirNum', 'fileNum']), '# Parsed Info', { isShowTime: false }); | ||
| fn.log(parsed.dirTree, '# Parsed Dir Tree', { isShowTime: false }); | ||
| const BaseInfo = fn.pick(parsed, prop => !['members', 'files', 'dirTree'].includes(prop)); | ||
| fn.log(BaseInfo, '# Parsed Info'); | ||
| fn.log(parsed.dirTree, '# Parsed Dir Tree'); | ||
| // fn.log(parsed.files, '# Parsed Dir Files'); | ||
| // fn.log(parsed.members, '# Parsed Dir Members'); | ||
Sorry, the diff of this file is not supported yet
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
Uses eval
Supply chain riskPackage uses dynamic code execution (e.g., eval()), which is a dangerous practice. This can prevent the code from running in certain environments and increases the risk that the code may contain exploits or malicious behavior.
Found 1 instance in 1 package
Dynamic require
Supply chain riskDynamic require can indicate the package is performing dangerous or unsafe dynamic code execution.
Found 1 instance in 1 package
Filesystem access
Supply chain riskAccesses the file system, and could potentially read sensitive data.
Found 1 instance in 1 package
91684
4.34%9
28.57%285
58.33%188
15.34%5
66.67%2
100%