Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

shelljs

Package Overview
Dependencies
Maintainers
3
Versions
53
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

shelljs - npm Package Compare versions

Comparing version 0.7.6 to 0.7.7

commands.js

14

CHANGELOG.md
# Change Log
## [Unreleased](https://github.com/shelljs/shelljs/tree/HEAD)
## [v0.7.6](https://github.com/shelljs/shelljs/tree/v0.7.6) (2017-01-08)
[Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.5...v0.7.6)
[Full Changelog](https://github.com/shelljs/shelljs/compare/v0.7.5...HEAD)
**Closed issues:**
- unable to execute ionic command with shell js [\#640](https://github.com/shelljs/shelljs/issues/640)
- How to increase ShellJS buffer size? [\#639](https://github.com/shelljs/shelljs/issues/639)
- mkdir fails with non-normalized path [\#634](https://github.com/shelljs/shelljs/issues/634)
- Move execPath into common [\#633](https://github.com/shelljs/shelljs/issues/633)
- QUESTION: Feedback while an operation is running? [\#629](https://github.com/shelljs/shelljs/issues/629)

@@ -38,2 +41,3 @@ - Test setup/cleanup is broken [\#621](https://github.com/shelljs/shelljs/issues/621)

- \[ Feature idea \] synchronous sleep command [\#441](https://github.com/shelljs/shelljs/issues/441)
- Improve test coverage [\#347](https://github.com/shelljs/shelljs/issues/347)
- Add a way to prevent shell-expansion on commands \(this issue is not for exec\) [\#345](https://github.com/shelljs/shelljs/issues/345)

@@ -48,2 +52,6 @@ - Chown [\#183](https://github.com/shelljs/shelljs/issues/183)

- refactor: add config.reset\(\) and .resetForTesting\(\) [\#641](https://github.com/shelljs/shelljs/pull/641) ([nfischer](https://github.com/nfischer))
- chore: set up test coverage [\#638](https://github.com/shelljs/shelljs/pull/638) ([nfischer](https://github.com/nfischer))
- refactor: create common.execPath [\#636](https://github.com/shelljs/shelljs/pull/636) ([nfischer](https://github.com/nfischer))
- fix: allow non-normalized paths as input to mkdir [\#635](https://github.com/shelljs/shelljs/pull/635) ([nfischer](https://github.com/nfischer))
- Finalize moving to ava [\#630](https://github.com/shelljs/shelljs/pull/630) ([freitagbr](https://github.com/freitagbr))

@@ -50,0 +58,0 @@ - test: refactor pushd tests to AVA [\#627](https://github.com/shelljs/shelljs/pull/627) ([nfischer](https://github.com/nfischer))

{
"name": "shelljs",
"version": "0.7.6",
"version": "0.7.7",
"description": "Portable Unix shell commands for Node.js",

@@ -27,3 +27,3 @@ "keywords": [

"files": [
"commands.json",
"commands.js",
"global.js",

@@ -44,2 +44,3 @@ "make.js",

"changelog": "shelljs-changelog",
"codecov": "codecov",
"release:major": "shelljs-release major",

@@ -59,2 +60,3 @@ "release:minor": "shelljs-release minor",

"ava": "^0.16.0",
"codecov": "^1.0.1",
"coffee-script": "^1.10.0",

@@ -61,0 +63,0 @@ "eslint": "^2.0.0",

@@ -6,17 +6,19 @@ # ShellJS - Unix shell commands for Node.js

[![AppVeyor](https://img.shields.io/appveyor/ci/shelljs/shelljs/master.svg?style=flat-square&label=windows)](https://ci.appveyor.com/project/shelljs/shelljs/branch/master)
[![Codecov](https://img.shields.io/codecov/c/github/shelljs/shelljs/master.svg?style=flat-square&label=coverage)](https://codecov.io/gh/shelljs/shelljs)
[![npm version](https://img.shields.io/npm/v/shelljs.svg?style=flat-square)](https://www.npmjs.com/package/shelljs)
[![npm downloads](https://img.shields.io/npm/dm/shelljs.svg?style=flat-square)](https://www.npmjs.com/package/shelljs)
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell commands on top of the
Node.js API. You can use it to eliminate your shell script's dependency on Unix while still keeping
its familiar and powerful commands. You can also install it globally so you can run it from outside
Node projects - say goodbye to those gnarly Bash scripts!
ShellJS is a portable **(Windows/Linux/OS X)** implementation of Unix shell
commands on top of the Node.js API. You can use it to eliminate your shell
script's dependency on Unix while still keeping its familiar and powerful
commands. You can also install it globally so you can run it from outside Node
projects - say goodbye to those gnarly Bash scripts!
ShellJS is proudly tested on every node release since `v0.11`!
The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battled-tested in projects like:
The project is [unit-tested](http://travis-ci.org/shelljs/shelljs) and battle-tested in projects like:
+ [PDF.js](http://github.com/mozilla/pdf.js) - Firefox's next-gen PDF reader
+ [Firebug](http://getfirebug.com/) - Firefox's infamous debugger
+ [JSHint](http://jshint.com) - Most popular JavaScript linter
+ [JSHint](http://jshint.com) & [ESLint](http://eslint.org/) - popular JavaScript linters
+ [Zepto](http://zeptojs.com) - jQuery-compatible JavaScript library for modern browsers

@@ -27,7 +29,7 @@ + [Yeoman](http://yeoman.io/) - Web application stack and development tool

If you have feedback, suggestions, or need help, feel free to post in our [issue tracker](https://github.com/shelljs/shelljs/issues).
If you have feedback, suggestions, or need help, feel free to post in our [issue
tracker](https://github.com/shelljs/shelljs/issues).
Think ShellJS is cool? Check out some related projects (like
[cash](https://github.com/dthree/cash)--a javascript-based POSIX shell)
in our [Wiki page](https://github.com/shelljs/shelljs/wiki)!
Think ShellJS is cool? Check out some related projects in our [Wiki
page](https://github.com/shelljs/shelljs/wiki)!

@@ -68,75 +70,39 @@ Upgrading from an older version? Check out our [breaking

If the global option `-g` is specified, the binary `shjs` will be installed. This makes it possible to
run ShellJS scripts much like any shell script from the command line, i.e. without requiring a `node_modules` folder:
```bash
$ shjs my_script
```
## Examples
### JavaScript
```javascript
require('shelljs/global');
var shell = require('shelljs');
if (!which('git')) {
echo('Sorry, this script requires git');
exit(1);
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
}
// Copy files to release dir
rm('-rf', 'out/Release');
cp('-R', 'stuff/', 'out/Release');
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');
// Replace macros in each .js file
cd('lib');
ls('*.js').forEach(function(file) {
sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file);
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, shell.cat('macro.js'), file);
});
cd('..');
shell.cd('..');
// Run external tool synchronously
if (exec('git commit -am "Auto-commit"').code !== 0) {
echo('Error: Git commit failed');
exit(1);
if (shell.exec('git commit -am "Auto-commit"').code !== 0) {
shell.echo('Error: Git commit failed');
shell.exit(1);
}
```
### CoffeeScript
CoffeeScript is also supported automatically:
```coffeescript
require 'shelljs/global'
if not which 'git'
echo 'Sorry, this script requires git'
exit 1
# Copy files to release dir
rm '-rf', 'out/Release'
cp '-R', 'stuff/', 'out/Release'
# Replace macros in each .js file
cd 'lib'
for file in ls '*.js'
sed '-i', 'BUILD_VERSION', 'v0.1.2', file
sed '-i', /^.*REMOVE_THIS_LINE.*$/, '', file
sed '-i', /.*REPLACE_LINE_WITH_MACRO.*\n/, cat('macro.js'), file
cd '..'
# Run external tool synchronously
if (exec 'git commit -am "Auto-commit"').code != 0
echo 'Error: Git commit failed'
exit 1
```
## Global vs. Local
The example above uses the convenience script `shelljs/global` to reduce verbosity. If polluting your global namespace is not desirable, simply require `shelljs`.
We no longer recommend using a global-import for ShellJS (i.e.
`require('shelljs/global')`). While still supported for convenience, this
pollutes the global namespace, and should therefore only be used with caution.
Example:
Instead, we recommend a local import (standard for npm packages):

@@ -183,4 +149,4 @@ ```javascript

### chmod(octal_mode || octal_string, file)
### chmod(symbolic_mode, file)
### chmod([options,] octal_mode || octal_string, file)
### chmod([options,] symbolic_mode, file)

@@ -199,2 +165,3 @@ Available options:

chmod('u+x', '/Users/brandon');
chmod('-R', 'a-w', '/Users/brandon');
```

@@ -318,3 +285,3 @@

+ `silent`: Do not echo program output to console.
+ and any option available to NodeJS's
+ and any option available to Node.js's
[child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)

@@ -426,2 +393,3 @@

+ `-A`: all files (include files beginning with `.`, except for `.` and `..`)
+ `-L`: follow symlinks
+ `-d`: list directories themselves, not their contents

@@ -822,4 +790,4 @@ + `-l`: list objects representing each file, each with fields containing `ls

| [![Nate Fischer](https://avatars.githubusercontent.com/u/5801521?s=130)](https://github.com/nfischer) | [![Ari Porad](https://avatars1.githubusercontent.com/u/1817508?v=3&s=130)](http://github.com/ariporad) |
| [![Nate Fischer](https://avatars.githubusercontent.com/u/5801521?s=130)](https://github.com/nfischer) | [![Brandon Freitag](https://avatars1.githubusercontent.com/u/5988055?v=3&s=130)](http://github.com/freitagbr) |
|:---:|:---:|
| [Nate Fischer](https://github.com/nfischer) | [Ari Porad](http://github.com/ariporad) |
| [Nate Fischer](https://github.com/nfischer) | [Brandon Freitag](http://github.com/freitagbr) |

@@ -24,3 +24,3 @@ //

// Load all default commands
require('./commands.json').forEach(function (command) {
require('./commands').forEach(function (command) {
require('./src/' + command);

@@ -27,0 +27,0 @@ });

@@ -24,3 +24,3 @@ var common = require('./common');

TYPE_MASK: parseInt('0770000', 8)
TYPE_MASK: parseInt('0770000', 8),
};

@@ -30,3 +30,3 @@ }({

WRITE: 2,
READ: 4
READ: 4,
}));

@@ -38,4 +38,4 @@

//@
//@ ### chmod(octal_mode || octal_string, file)
//@ ### chmod(symbolic_mode, file)
//@ ### chmod([options,] octal_mode || octal_string, file)
//@ ### chmod([options,] symbolic_mode, file)
//@

@@ -54,2 +54,3 @@ //@ Available options:

//@ chmod('u+x', '/Users/brandon');
//@ chmod('-R', 'a-w', '/Users/brandon');
//@ ```

@@ -80,3 +81,3 @@ //@

'c': 'changes',
'v': 'verbose'
'v': 'verbose',
});

@@ -83,0 +84,0 @@

@@ -63,3 +63,3 @@ // Ignore warning about 'new String()'

currentCmd: 'shell.js',
tempDir: null
tempDir: null,
};

@@ -76,3 +76,10 @@ exports.state = state;

// Reliably test if something is any sort of javascript object
function isObject(a) {
return typeof a === 'object' && a !== null;
}
exports.isObject = isObject;
function log() {
/* istanbul ignore next */
if (!config.silent) {

@@ -84,2 +91,13 @@ console.error.apply(console, arguments);

// Converts strings to be equivalent across all platforms. Primarily responsible
// for making sure we use '/' instead of '\' as path separators, but this may be
// expanded in the future if necessary
function convertErrorOutput(msg) {
if (typeof msg !== 'string') {
throw new TypeError('input must be a string');
}
return msg.replace(/\\/g, '/');
}
exports.convertErrorOutput = convertErrorOutput;
// Shows error message. Throws if config.fatal is true

@@ -97,5 +115,5 @@ function error(msg, _code, options) {

if (typeof _code === 'number' && typeof options === 'object') {
if (typeof _code === 'number' && isObject(options)) {
options.code = _code;
} else if (typeof _code === 'object') { // no 'code'
} else if (isObject(_code)) { // no 'code'
options = _code;

@@ -111,3 +129,3 @@ } else if (typeof _code === 'number') { // no 'options'

var logEntry = options.prefix + msg;
var logEntry = convertErrorOutput(options.prefix + msg);
state.error = state.error ? state.error + '\n' : '';

@@ -123,3 +141,3 @@ state.error += logEntry;

msg: 'earlyExit',
retValue: (new ShellString('', state.error, state.errorCode))
retValue: (new ShellString('', state.error, state.errorCode)),
};

@@ -181,3 +199,10 @@ }

function parseOptions(opt, map, errorOptions) {
if (!map) error('parseOptions() internal error: no map given');
// Validate input
if (typeof opt !== 'string' && !isObject(opt)) {
throw new Error('options must be strings or key-value pairs');
} else if (!isObject(map)) {
throw new Error('parseOptions() internal error: map must be an object');
} else if (errorOptions && !isObject(errorOptions)) {
throw new Error('parseOptions() internal error: errorOptions must be object');
}

@@ -187,13 +212,13 @@ // All options are false by default

Object.keys(map).forEach(function (letter) {
if (map[letter][0] !== '!') {
options[map[letter]] = false;
var optName = map[letter];
if (optName[0] !== '!') {
options[optName] = false;
}
});
if (!opt) return options; // defaults
if (opt === '') return options; // defaults
var optionName;
if (typeof opt === 'string') {
if (opt[0] !== '-') {
return options;
error("Options string must start with a '-'", errorOptions || {});
}

@@ -206,3 +231,3 @@

if (c in map) {
optionName = map[c];
var optionName = map[c];
if (optionName[0] === '!') {

@@ -213,9 +238,7 @@ options[optionName.slice(1)] = false;

}
} else if (typeof errorOptions === 'object') {
error('option not recognized: ' + c, errorOptions);
} else {
error('option not recognized: ' + c);
error('option not recognized: ' + c, errorOptions || {});
}
});
} else if (typeof opt === 'object') {
} else { // opt is an Object
Object.keys(opt).forEach(function (key) {

@@ -225,14 +248,8 @@ // key is a string of the form '-r', '-d', etc.

if (c in map) {
optionName = map[c];
var optionName = map[c];
options[optionName] = opt[key]; // assign the given value
} else if (typeof errorOptions === 'object') {
error('option not recognized: ' + c, errorOptions);
} else {
error('option not recognized: ' + c);
error('option not recognized: ' + c, errorOptions || {});
}
});
} else if (typeof errorOptions === 'object') {
error('options must be strings or key-value pairs', errorOptions);
} else {
error('options must be strings or key-value pairs');
}

@@ -273,2 +290,3 @@ return options;

// Try to override file permission
/* istanbul ignore next */
if (e.code === 'EPERM') {

@@ -330,3 +348,3 @@ fs.chmodSync(file, '0666');

} else { // and this branch is for everything else
if (args[0] instanceof Object && args[0].constructor.name === 'Object') {
if (isObject(args[0]) && args[0].constructor.name === 'Object') {
// a no-op, allowing the syntax `touch({'-r': file}, ...)`

@@ -351,3 +369,3 @@ } else if (args.length === 0 || typeof args[0] !== 'string' || args[0].length <= 1 || args[0][0] !== '-') {

args = args.map(function (arg) {
if (arg instanceof Object && arg.constructor.name === 'String') {
if (isObject(arg) && arg.constructor.name === 'String') {
return arg.toString();

@@ -375,3 +393,3 @@ }

// parse options if options are provided
if (typeof options.cmdOptions === 'object') {
if (isObject(options.cmdOptions)) {
args[0] = parseOptions(args[0], options.cmdOptions);

@@ -382,2 +400,3 @@ }

} catch (e) {
/* istanbul ignore else */
if (e.msg === 'earlyExit') {

@@ -391,2 +410,3 @@ retValue = e.retValue;

} catch (e) {
/* istanbul ignore next */
if (!state.error) {

@@ -393,0 +413,0 @@ // If state.error hasn't been set it's an error thrown by Node, not us - probably a bug...

@@ -57,2 +57,3 @@ var fs = require('fs');

} catch (e) {
/* istanbul ignore next */
common.error('copyFileSync: could not read src file (' + srcFile + ')');

@@ -64,2 +65,3 @@ }

} catch (e) {
/* istanbul ignore next */
common.error('copyFileSync: could not write to dest file (code=' + e.code + '):' + destFile);

@@ -248,2 +250,3 @@ }

} catch (e) {
/* istanbul ignore next */
common.error("cannot create directory '" + dest + "': No such file or directory");

@@ -266,7 +269,14 @@ }

if (path.relative(src, thisDest) === '') {
// a file cannot be copied to itself, but we want to continue copying other files
common.error("'" + thisDest + "' and '" + src + "' are the same file", { continue: true });
return;
}
copyFileSync(src, thisDest, options);
}
}); // forEach(src)
return new common.ShellString('', common.state.error, common.state.errorCode);
}
module.exports = _cp;

@@ -66,3 +66,3 @@ var common = require('./common');

options = common.parseOptions(options, {
'n': 'no-cd'
'n': 'no-cd',
});

@@ -133,3 +133,3 @@

options = common.parseOptions(options, {
'n': 'no-cd'
'n': 'no-cd',
});

@@ -177,3 +177,3 @@

options = common.parseOptions(options, {
'c': 'clear'
'c': 'clear',
});

@@ -180,0 +180,0 @@

@@ -37,3 +37,3 @@ var common = require('./common');

env: process.env,
maxBuffer: DEFAULT_MAXBUFFER_SIZE
maxBuffer: DEFAULT_MAXBUFFER_SIZE,
}, opts);

@@ -194,3 +194,3 @@

env: process.env,
maxBuffer: DEFAULT_MAXBUFFER_SIZE
maxBuffer: DEFAULT_MAXBUFFER_SIZE,
}, opts);

@@ -233,3 +233,3 @@

//@ + `silent`: Do not echo program output to console.
//@ + and any option available to NodeJS's
//@ + and any option available to Node.js's
//@ [child_process.exec()](https://nodejs.org/api/child_process.html#child_process_child_process_exec_command_options_callback)

@@ -285,3 +285,3 @@ //@

silent: common.config.silent,
async: false
async: false,
}, options);

@@ -288,0 +288,0 @@

@@ -43,5 +43,12 @@ var fs = require('fs');

paths.forEach(function (file) {
var stat;
try {
stat = fs.statSync(file);
} catch (e) {
common.error('no such file or directory: ' + file);
}
pushFile(file);
if (fs.statSync(file).isDirectory()) {
if (stat.isDirectory()) {
_ls({ recursive: true, all: true }, file).forEach(function (subfile) {

@@ -48,0 +55,0 @@ pushFile(path.join(file, subfile));

@@ -6,3 +6,3 @@ var path = require('path');

var globPatternRecursive = path.sep + '**' + path.sep + '*';
var globPatternRecursive = path.sep + '**';

@@ -13,2 +13,3 @@ common.register('ls', _ls, {

'A': 'all',
'L': 'link',
'a': 'all_deprecated',

@@ -27,2 +28,3 @@ 'd': 'directory',

//@ + `-A`: all files (include files beginning with `.`, except for `.` and `..`)
//@ + `-L`: follow symlinks
//@ + `-d`: list directories themselves, not their contents

@@ -66,3 +68,3 @@ //@ + `-l`: list objects representing each file, each with fields containing `ls

if (options.long) {
stat = stat || fs.lstatSync(abs);
stat = stat || (options.link ? fs.statSync(abs) : fs.lstatSync(abs));
list.push(addLsAttributes(relName, stat));

@@ -79,3 +81,3 @@ } else {

try {
stat = fs.lstatSync(p);
stat = options.link ? fs.statSync(p) : fs.lstatSync(p);
} catch (e) {

@@ -90,5 +92,8 @@ common.error('no such file or directory: ' + p, 2, { continue: true });

// use glob, because it's simple
glob.sync(p + globPatternRecursive, { dot: options.all })
glob.sync(p + globPatternRecursive, { dot: options.all, follow: options.link })
.forEach(function (item) {
pushFile(item, path.relative(p, item));
// Glob pattern returns the directory itself and needs to be filtered out.
if (path.relative(p, item)) {
pushFile(item, path.relative(p, item));
}
});

@@ -95,0 +100,0 @@ } else if (options.all) {

@@ -86,2 +86,3 @@ var common = require('./common');

} else {
/* istanbul ignore next */
throw e;

@@ -88,0 +89,0 @@ }

@@ -41,2 +41,3 @@ var fs = require('fs');

} else {
// TODO(nate): figure out if we actually need this line
common.error('invalid arguments');

@@ -86,5 +87,8 @@ }

} catch (e) {
if (e.code === 'EXDEV') { // external partition
// if either of these fails, the appropriate error message will bubble
// up to the top level automatically
/* istanbul ignore next */
if (e.code === 'EXDEV') {
// If we're trying to `mv` to an external partition, we'll actually need
// to perform a copy and then clean up the original file. If either the
// copy or the rm fails with an exception, we should allow this
// exception to pass up to the top level.
cp('-r', src, thisDest);

@@ -91,0 +95,0 @@ rm('-rf', src);

@@ -37,3 +37,6 @@ var common = require('./common');

} catch (e) {
common.error('could not remove file (code ' + e.code + '): ' + file, { continue: true });
/* istanbul ignore next */
common.error('could not remove file (code ' + e.code + '): ' + file, {
continue: true,
});
}

@@ -59,2 +62,3 @@ }

} catch (er) {
/* istanbul ignore next */
// In addition to error codes, also check if the directory still exists and loop again if true

@@ -142,3 +146,3 @@ if (process.platform === 'win32' && (er.code === 'ENOTEMPTY' || er.code === 'EBUSY' || er.code === 'EPERM' || er.code === 'EAGAIN')) {

}
} else if (stats.isSymbolicLink()) {
} else if (stats.isSymbolicLink() || stats.isFIFO()) {
common.unlinkSync(file);

@@ -145,0 +149,0 @@ }

@@ -37,3 +37,3 @@ var common = require('./common');

'v': 'verbose',
'f': 'noglob'
'f': 'noglob',
});

@@ -40,0 +40,0 @@

@@ -22,2 +22,3 @@ var common = require('./common');

} catch (e) {
/* istanbul ignore next */
return false;

@@ -24,0 +25,0 @@ }

@@ -75,8 +75,11 @@ var common = require('./common');

/* istanbul ignore next */
if (options.pipe) return stats.isFIFO();
/* istanbul ignore next */
if (options.socket) return stats.isSocket();
/* istanbul ignore next */
return false; // fallback
} // test
module.exports = _test;

@@ -33,2 +33,3 @@ var common = require('./common');

} catch (e) {
/* istanbul ignore next */
common.error('could not write to file (code ' + e.code + '): ' + file, { continue: true });

@@ -35,0 +36,0 @@ }

@@ -32,2 +32,3 @@ var common = require('./common');

} catch (e) {
/* istanbul ignore next */
common.error('could not append to file (code ' + e.code + '): ' + file, { continue: true });

@@ -34,0 +35,0 @@ }

@@ -7,2 +7,5 @@ var common = require('./common');

allowGlobbing: false,
cmdOptions: {
'a': 'all',
},
});

@@ -16,9 +19,3 @@

function splitPath(p) {
if (!p) return [];
if (common.platform === 'win') {
return p.split(';');
} else {
return p.split(':');
}
return p ? p.split(path.delimiter) : [];
}

@@ -47,56 +44,58 @@

var pathArray = splitPath(pathEnv);
var where = null;
var queryMatches = [];
// No relative/absolute paths provided?
if (cmd.search(/\//) === -1) {
if (cmd.indexOf('/') === -1) {
// Assume that there are no extensions to append to queries (this is the
// case for unix)
var pathExtArray = [''];
if (common.platform === 'win') {
// In case the PATHEXT variable is somehow not set (e.g.
// child_process.spawn with an empty environment), use the XP default.
var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT;
pathExtArray = splitPath(pathExtEnv.toUpperCase());
}
// Search for command in PATH
pathArray.forEach(function (dir) {
if (where) return; // already found it
for (var k = 0; k < pathArray.length; k++) {
// already found it
if (queryMatches.length > 0 && !options.all) break;
var attempt = path.resolve(dir, cmd);
var attempt = path.resolve(pathArray[k], cmd);
if (common.platform === 'win') {
attempt = attempt.toUpperCase();
}
// In case the PATHEXT variable is somehow not set (e.g.
// child_process.spawn with an empty environment), use the XP default.
var pathExtEnv = process.env.PATHEXT || XP_DEFAULT_PATHEXT;
var pathExtArray = splitPath(pathExtEnv.toUpperCase());
var i;
// If the extension is already in PATHEXT, just return that.
for (i = 0; i < pathExtArray.length; i++) {
var match = attempt.match(/\.[^<>:"/\|?*.]+$/);
if (match && pathExtArray.indexOf(match[0]) >= 0) { // this is Windows-only
// The user typed a query with the file extension, like
// `which('node.exe')`
if (checkPath(attempt)) {
queryMatches.push(attempt);
break;
}
} else { // All-platforms
// Cycle through the PATHEXT array, and check each extension
// Note: the array is always [''] on Unix
for (var i = 0; i < pathExtArray.length; i++) {
var ext = pathExtArray[i];
if (attempt.slice(-ext.length) === ext && checkPath(attempt)) {
where = attempt;
return;
var newAttempt = attempt + ext;
if (checkPath(newAttempt)) {
queryMatches.push(newAttempt);
break;
}
}
// Cycle through the PATHEXT variable
var baseAttempt = attempt;
for (i = 0; i < pathExtArray.length; i++) {
attempt = baseAttempt + pathExtArray[i];
if (checkPath(attempt)) {
where = attempt;
return;
}
}
} else {
// Assume it's Unix-like
if (checkPath(attempt)) {
where = attempt;
return;
}
}
});
}
} else if (checkPath(cmd)) { // a valid absolute or relative path
queryMatches.push(path.resolve(cmd));
}
// Command not found anywhere?
if (!checkPath(cmd) && !where) return null;
where = where || path.resolve(cmd);
return where;
if (queryMatches.length > 0) {
return options.all ? queryMatches : queryMatches[0];
}
return options.all ? [] : null;
}
module.exports = _which;
SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc