├── README.md ├── bin └── tree2 ├── index.js ├── package.json └── tea.yaml /README.md: -------------------------------------------------------------------------------- 1 | ## 模仿linux tree 2 | **可以做到文件过滤,使其使用更方便** 3 | 4 | #### 安装 5 | ``` 6 | $npm install tree2 -g 7 | ``` 8 | 9 | #### 使用 10 | ``` 11 | $tree2 12 | ``` 13 | #### show 某个文件夹下内容 14 | ``` 15 | $tree2 /xx/xx/x 16 | ``` 17 | #### 查看常规Node.js 文件目录树 18 | **不展开node_modules, 同时进行配色** 19 | ``` 20 | $tree2 -a 21 | ``` 22 | #### 对文件树进行保存 23 | **将该文件树保存到该命令下的tree2.md** 24 | ``` 25 | $tree2 -s 26 | ``` 27 | #### 详细例子 28 | **如将/usr/local 下文件进行tree, 并且配色, 不展开 node_modules, go 两个文件夹下的内容, 最后保存** 29 | ``` 30 | $tree2 -c -i go,node_modules -s /usr/local 31 | ``` 32 | 33 | #### 具体用法 34 | ``` 35 | $tree2 -h 36 | ``` 37 | #### 更新 38 | ``` 39 | $tree2 update 40 | ``` 41 | 42 | **有任何问题,可联系:shanquan54@gmail.com** -------------------------------------------------------------------------------- /bin/tree2: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | 'use strict'; 4 | 5 | var commander = require('commander'); 6 | var API = require('../index'); 7 | var pkg = require('../package.json'); 8 | var ENABLE = true; 9 | 10 | commander.version(pkg.version) 11 | .option('-i, --ignore ', 'floder/files to be ignored', (val) => { 12 | return val.split(',') 13 | }) 14 | .option('-a, --auto', 'auto create Node.js project tree, ignore node_modules/* add color schemes') 15 | .option('-c, --color', 'add color schemes') 16 | .option('-s, --save', 'create a .md file ./tree2.md') 17 | .usage('[options] '); 18 | 19 | commander.on('--help', function () { 20 | console.log(' Basic Examples:'); 21 | console.log(''); 22 | console.log(' Start :'); 23 | console.log(' $tree2 '); 24 | 25 | console.log(' Auto Node.js tree2 :'); 26 | console.log(' $tree2 -a'); 27 | console.log(''); 28 | console.log(' Show others dir :'); 29 | console.log(' $tree2 /usr/local'); 30 | console.log(''); 31 | console.log(' Ignore [nodele_module,bin ...] floder'); 32 | console.log(' $tree2 -i node-module, bin'); 33 | console.log(''); 34 | 35 | }); 36 | 37 | commander.command('update') 38 | .description('update tree2') 39 | .action(function () { 40 | ENABLE = false; 41 | API.update(); 42 | }); 43 | 44 | commander.parse(process.argv); 45 | 46 | let opt = {}; 47 | opt.dir = commander.args[0] || process.cwd(); 48 | opt.ignore = commander.ignore || []; 49 | opt.color = commander.color; 50 | opt.save = commander.save; 51 | if (commander.auto) { 52 | opt.ignore.push('node_modules'); 53 | opt.color = true 54 | } 55 | 56 | if (ENABLE) { 57 | 58 | API.result(opt); 59 | } 60 | -------------------------------------------------------------------------------- /index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Created by yujintang on 2017/3/19. 3 | */ 4 | 'use strict'; 5 | 6 | const fs = require('fs'), 7 | path = require('path'), 8 | execa = require('execa'), 9 | chalk = require('chalk'); 10 | 11 | 12 | exports.result = function (opt) { 13 | console.log('\n'); 14 | let res = stru(createObj(opt.dir, opt, 0), [], opt).join('\n'); 15 | console.log(res); 16 | opt.save && tree2File(opt, res); 17 | return res; 18 | }; 19 | /** 20 | * 读取到的文件变为数组对象 21 | * @param dir 22 | * @param opt 23 | * @returns {Array} 24 | */ 25 | function createObj(dir, opt, layer) { 26 | 27 | let array = []; 28 | if (++layer > 10) { 29 | return array; 30 | } 31 | let dirArray = fs.readdirSync(dir).sort(orderedDict); 32 | for (let file of dirArray) { 33 | let tempDir = path.join(dir, file); 34 | if (!/^\./.test(file) && fs.existsSync(tempDir)) { 35 | let obj = {}; 36 | obj.name = file; 37 | let stats = fs.statSync(tempDir); 38 | obj.size = stats.size; 39 | if (stats.isFile()) { 40 | obj.type = 'File' 41 | } 42 | if (stats.isDirectory()) { 43 | obj.type = 'Directory' 44 | } 45 | if (stats.isBlockDevice()) { 46 | obj.type = 'BlockDevice' 47 | } 48 | if (stats.isCharacterDevice()) { 49 | obj.type = 'CharacterDevice' 50 | } 51 | if (stats.isSymbolicLink()) { 52 | obj.type = 'SymbolicLink' 53 | } 54 | if (stats.isFIFO()) { 55 | obj.type = 'FIFO' 56 | } 57 | if (stats.isSocket()) { 58 | obj.type = 'Socket' 59 | } 60 | 61 | if (obj.type == 'Directory' && !opt.ignore.includes(obj.name)) { 62 | obj.children = createObj(path.join(dir, file), opt, layer) 63 | } 64 | array.push(obj); 65 | } 66 | } 67 | 68 | return array; 69 | } 70 | 71 | /** 72 | * 数据结构转换为图 73 | * @param data 数据结构 74 | * @param pre tree结构前缀 75 | * @param opt tree 参数 76 | * @returns {Array} 77 | */ 78 | function stru(data, pre, opt) { 79 | let array = []; 80 | if (!data) { 81 | return array 82 | } 83 | data.forEach((node, index) => { 84 | let last = index == data.length - 1; 85 | node = colorName(node, opt); 86 | let line = pre.concat(last ? '└── ' : '├── ', node.name).join(''); 87 | array = array.concat(line); 88 | let tempPre = pre.concat(last ? ' ' : '│ '); 89 | array = array.concat(stru(node.children, tempPre, opt)); 90 | }); 91 | return array; 92 | }; 93 | 94 | /** 95 | * 排序 以字典排序 96 | */ 97 | function orderedDict(a, b) { 98 | a = a.toLowerCase(); 99 | b = b.toLowerCase(); 100 | if (a > b) { 101 | return 1 102 | } else if (a < b) { 103 | return -1 104 | } else { 105 | return 0 106 | } 107 | } 108 | 109 | /** 110 | * 文件颜色变换 111 | * @param opt 112 | */ 113 | function colorName(obj, opt) { 114 | if (!opt.color) { 115 | return obj 116 | } 117 | if (obj.type == 'Directory') { 118 | obj.name = chalk.blue(obj.name); 119 | } 120 | if (path.extname(obj.name) == '.md') { 121 | obj.name = chalk.red(obj.name); 122 | } 123 | if (path.extname(obj.name) == '.json') { 124 | obj.name = chalk.red(obj.name); 125 | } 126 | if (path.extname(obj.name) == '.js') { 127 | obj.name = path.basename(obj.name, '.js') + chalk.green('.js'); 128 | } 129 | if (path.extname(obj.name) == '.css') { 130 | obj.name = path.basename(obj.name, '.css') + chalk.magenta('.css'); 131 | } 132 | if (path.extname(obj.name) == '.vue') { 133 | obj.name = path.basename(obj.name, '.vue') + chalk.cyan('.vue'); 134 | } 135 | if (path.extname(obj.name) == '.html') { 136 | obj.name = path.basename(obj.name, '.html') + chalk.blue('.html'); 137 | } 138 | return obj; 139 | } 140 | 141 | function tree2File(opt, data) { 142 | if (!opt.color) { 143 | data = '###文件生成树\n**有任何问题,请联系shanquan54@gmail.com**\n```\n' + '\n' + data + '\n```\n'; 144 | } else { 145 | opt.color = false; 146 | let res = stru(createObj(opt.dir, opt, 0), [], opt).join('\n'); 147 | data = '###文件生成树\n**有任何问题,请联系shanquan54@gmail.com**\n```\n' + res + '\n```\n'; 148 | } 149 | fs.appendFileSync(path.join(process.cwd(), 'tree2.md'), data); 150 | } 151 | 152 | /** 153 | * tree2 版本升级 154 | */ 155 | exports.update = function () { 156 | console.log(chalk.green('[tree2] ') + 'Be sure to have the latest version by doing `npm install tree2@latest -g` before doing this procedure.'); 157 | console.log(chalk.green('[tree2] ') + 'Start update...'); 158 | execa.stdout('npm', ['install', 'tree2', '-g']) 159 | .then(result => { 160 | console.log(chalk.green('[tree2] ') + 'Upgrade success!\n' + result) 161 | }) 162 | .catch(e => { 163 | console.log(chalk.green('[tree2] ') + 'Upgrade failed\n' + e); 164 | }) 165 | }; 166 | 167 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "tree2", 3 | "version": "1.0.13", 4 | "description": "文件目录树", 5 | "main": "index.js", 6 | "scripts": { 7 | "test": "echo \"Error: no test specified\" && exit 1" 8 | }, 9 | "bin": { 10 | "tree2": "./bin/tree2" 11 | }, 12 | "homepage": "https://github.com/yujintang/tree2#readme", 13 | "author": "yujintang ", 14 | "license": "ISC", 15 | "repository": { 16 | "type": "git", 17 | "url": "git+https://github.com/yujintang/tree2.git" 18 | }, 19 | "dependencies": { 20 | "chalk": "^1.1.3", 21 | "commander": "^2.9.0", 22 | "execa": "^0.6.2" 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /tea.yaml: -------------------------------------------------------------------------------- 1 | # https://tea.xyz/what-is-this-file 2 | --- 3 | version: 1.0.0 4 | codeOwners: 5 | - '0xcb50b5589196882b5Af8b4a41F7B441D7112957C' 6 | quorum: 1 7 | --------------------------------------------------------------------------------