| var path = require('path'); |
| var fs = require('fs'); |
| var common = require('./common'); |
| var _cd = require('./cd'); |
| var _pwd = require('./pwd'); |
| |
| //@ |
| //@ ### ls([options ,] path [,path ...]) |
| //@ ### ls([options ,] path_array) |
| //@ Available options: |
| //@ |
| //@ + `-R`: recursive |
| //@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`) |
| //@ |
| //@ Examples: |
| //@ |
| //@ ```javascript |
| //@ ls('projs/*.js'); |
| //@ ls('-R', '/users/me', '/tmp'); |
| //@ ls('-R', ['/users/me', '/tmp']); // same as above |
| //@ ``` |
| //@ |
| //@ Returns array of files in the given path, or in current directory if no path provided. |
| function _ls(options, paths) { |
| options = common.parseOptions(options, { |
| 'R': 'recursive', |
| 'A': 'all', |
| 'a': 'all_deprecated' |
| }); |
| |
| if (options.all_deprecated) { |
| // We won't support the -a option as it's hard to image why it's useful |
| // (it includes '.' and '..' in addition to '.*' files) |
| // For backwards compatibility we'll dump a deprecated message and proceed as before |
| common.log('ls: Option -a is deprecated. Use -A instead'); |
| options.all = true; |
| } |
| |
| if (!paths) |
| paths = ['.']; |
| else if (typeof paths === 'object') |
| paths = paths; // assume array |
| else if (typeof paths === 'string') |
| paths = [].slice.call(arguments, 1); |
| |
| var list = []; |
| |
| // Conditionally pushes file to list - returns true if pushed, false otherwise |
| // (e.g. prevents hidden files to be included unless explicitly told so) |
| function pushFile(file, query) { |
| // hidden file? |
| if (path.basename(file)[0] === '.') { |
| // not explicitly asking for hidden files? |
| if (!options.all && !(path.basename(query)[0] === '.' && path.basename(query).length > 1)) |
| return false; |
| } |
| |
| if (common.platform === 'win') |
| file = file.replace(/\\/g, '/'); |
| |
| list.push(file); |
| return true; |
| } |
| |
| paths.forEach(function(p) { |
| if (fs.existsSync(p)) { |
| var stats = fs.statSync(p); |
| // Simple file? |
| if (stats.isFile()) { |
| pushFile(p, p); |
| return; // continue |
| } |
| |
| // Simple dir? |
| if (stats.isDirectory()) { |
| // Iterate over p contents |
| fs.readdirSync(p).forEach(function(file) { |
| if (!pushFile(file, p)) |
| return; |
| |
| // Recursive? |
| if (options.recursive) { |
| var oldDir = _pwd(); |
| _cd('', p); |
| if (fs.statSync(file).isDirectory()) |
| list = list.concat(_ls('-R'+(options.all?'A':''), file+'/*')); |
| _cd('', oldDir); |
| } |
| }); |
| return; // continue |
| } |
| } |
| |
| // p does not exist - possible wildcard present |
| |
| var basename = path.basename(p); |
| var dirname = path.dirname(p); |
| // Wildcard present on an existing dir? (e.g. '/tmp/*.js') |
| if (basename.search(/\*/) > -1 && fs.existsSync(dirname) && fs.statSync(dirname).isDirectory) { |
| // Escape special regular expression chars |
| var regexp = basename.replace(/(\^|\$|\(|\)|<|>|\[|\]|\{|\}|\.|\+|\?)/g, '\\$1'); |
| // Translates wildcard into regex |
| regexp = '^' + regexp.replace(/\*/g, '.*') + '$'; |
| // Iterate over directory contents |
| fs.readdirSync(dirname).forEach(function(file) { |
| if (file.match(new RegExp(regexp))) { |
| if (!pushFile(path.normalize(dirname+'/'+file), basename)) |
| return; |
| |
| // Recursive? |
| if (options.recursive) { |
| var pp = dirname + '/' + file; |
| if (fs.lstatSync(pp).isDirectory()) |
| list = list.concat(_ls('-R'+(options.all?'A':''), pp+'/*')); |
| } // recursive |
| } // if file matches |
| }); // forEach |
| return; |
| } |
| |
| common.error('no such file or directory: ' + p, true); |
| }); |
| |
| return list; |
| } |
| module.exports = _ls; |