UNPKG

4.35 kBJavaScriptView Raw
1var path = require('path');
2var fs = require('fs');
3var common = require('./common');
4var glob = require('glob');
5
6var globPatternRecursive = path.sep + '**';
7
8common.register('ls', _ls, {
9 cmdOptions: {
10 'R': 'recursive',
11 'A': 'all',
12 'L': 'link',
13 'a': 'all_deprecated',
14 'd': 'directory',
15 'l': 'long',
16 },
17});
18
19//@
20//@ ### ls([options,] [path, ...])
21//@ ### ls([options,] path_array)
22//@
23//@ Available options:
24//@
25//@ + `-R`: recursive
26//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
27//@ + `-L`: follow symlinks
28//@ + `-d`: list directories themselves, not their contents
29//@ + `-l`: list objects representing each file, each with fields containing `ls
30//@ -l` output fields. See
31//@ [`fs.Stats`](https://nodejs.org/api/fs.html#fs_class_fs_stats)
32//@ for more info
33//@
34//@ Examples:
35//@
36//@ ```javascript
37//@ ls('projs/*.js');
38//@ ls('-R', '/users/me', '/tmp');
39//@ ls('-R', ['/users/me', '/tmp']); // same as above
40//@ ls('-l', 'file.txt'); // { name: 'file.txt', mode: 33188, nlink: 1, ...}
41//@ ```
42//@
43//@ Returns array of files in the given `path`, or files in
44//@ the current directory if no `path` is provided.
45function _ls(options, paths) {
46 if (options.all_deprecated) {
47 // We won't support the -a option as it's hard to image why it's useful
48 // (it includes '.' and '..' in addition to '.*' files)
49 // For backwards compatibility we'll dump a deprecated message and proceed as before
50 common.log('ls: Option -a is deprecated. Use -A instead');
51 options.all = true;
52 }
53
54 if (!paths) {
55 paths = ['.'];
56 } else {
57 paths = [].slice.call(arguments, 1);
58 }
59
60 var list = [];
61
62 function pushFile(abs, relName, stat) {
63 if (process.platform === 'win32') {
64 relName = relName.replace(/\\/g, '/');
65 }
66 if (options.long) {
67 stat = stat || (options.link ? common.statFollowLinks(abs) : common.statNoFollowLinks(abs));
68 list.push(addLsAttributes(relName, stat));
69 } else {
70 // list.push(path.relative(rel || '.', file));
71 list.push(relName);
72 }
73 }
74
75 paths.forEach(function (p) {
76 var stat;
77
78 try {
79 stat = options.link ? common.statFollowLinks(p) : common.statNoFollowLinks(p);
80 // follow links to directories by default
81 if (stat.isSymbolicLink()) {
82 /* istanbul ignore next */
83 // workaround for https://github.com/shelljs/shelljs/issues/795
84 // codecov seems to have a bug that miscalculate this block as uncovered.
85 // but according to nyc report this block does get covered.
86 try {
87 var _stat = common.statFollowLinks(p);
88 if (_stat.isDirectory()) {
89 stat = _stat;
90 }
91 } catch (_) {} // bad symlink, treat it like a file
92 }
93 } catch (e) {
94 common.error('no such file or directory: ' + p, 2, { continue: true });
95 return;
96 }
97
98 // If the stat succeeded
99 if (stat.isDirectory() && !options.directory) {
100 if (options.recursive) {
101 // use glob, because it's simple
102 glob.sync(p + globPatternRecursive, { dot: options.all, follow: options.link })
103 .forEach(function (item) {
104 // Glob pattern returns the directory itself and needs to be filtered out.
105 if (path.relative(p, item)) {
106 pushFile(item, path.relative(p, item));
107 }
108 });
109 } else if (options.all) {
110 // use fs.readdirSync, because it's fast
111 fs.readdirSync(p).forEach(function (item) {
112 pushFile(path.join(p, item), item);
113 });
114 } else {
115 // use fs.readdirSync and then filter out secret files
116 fs.readdirSync(p).forEach(function (item) {
117 if (item[0] !== '.') {
118 pushFile(path.join(p, item), item);
119 }
120 });
121 }
122 } else {
123 pushFile(p, p, stat);
124 }
125 });
126
127 // Add methods, to make this more compatible with ShellStrings
128 return list;
129}
130
131function addLsAttributes(pathName, stats) {
132 // Note: this object will contain more information than .toString() returns
133 stats.name = pathName;
134 stats.toString = function () {
135 // Return a string resembling unix's `ls -l` format
136 return [this.mode, this.nlink, this.uid, this.gid, this.size, this.mtime, this.name].join(' ');
137 };
138 return stats;
139}
140
141module.exports = _ls;