Like which(1) unix command - finds the first instance of an executable in the PATH.
npx @tessl/cli install tessl/npm-which@5.0.00
# Which
1
2
Like the Unix `which(1)` command, this package finds the first instance of a specified executable in the PATH environment variable. It provides both asynchronous and synchronous APIs with comprehensive cross-platform support and does not cache results, making it ideal for dynamic environments where executables may be added or removed frequently.
3
4
## Package Information
5
6
- **Package Name**: which
7
- **Package Type**: npm
8
- **Language**: JavaScript
9
- **Installation**: `npm install which`
10
11
## Core Imports
12
13
```javascript
14
const which = require('which');
15
```
16
17
For ES modules (when using Node.js with ES module support):
18
19
```javascript
20
import which from 'which';
21
```
22
23
## Basic Usage
24
25
```javascript
26
const which = require('which');
27
28
// Async usage - finds executable in PATH
29
try {
30
const resolved = await which('node');
31
console.log('Node.js found at:', resolved);
32
} catch (error) {
33
console.log('Node.js not found');
34
}
35
36
// Sync usage - finds executable in PATH
37
try {
38
const resolved = which.sync('node');
39
console.log('Node.js found at:', resolved);
40
} catch (error) {
41
console.log('Node.js not found');
42
}
43
44
// With nothrow option - returns null instead of throwing
45
const resolvedOrNull = await which('node', { nothrow: true });
46
if (resolvedOrNull) {
47
console.log('Found:', resolvedOrNull);
48
} else {
49
console.log('Not found');
50
}
51
```
52
53
## Capabilities
54
55
### Async Executable Search
56
57
Asynchronously searches for executable in PATH environment variable.
58
59
```javascript { .api }
60
/**
61
* Asynchronously find the first instance of an executable in PATH
62
* @param {string} cmd - Name of the executable to find
63
* @param {Object} [options] - Configuration options
64
* @param {string} [options.path] - Override PATH environment variable
65
* @param {string} [options.pathExt] - Override PATHEXT environment variable (Windows)
66
* @param {string} [options.delimiter] - Override path delimiter
67
* @param {boolean} [options.all=false] - Return all matches instead of just the first
68
* @param {boolean} [options.nothrow=false] - Return null instead of throwing when not found
69
* @returns {Promise<string|string[]|null>} Path to executable, array of paths (if all=true), or null (if nothrow=true and not found)
70
* @throws {Error} Error with code 'ENOENT' if executable not found (unless nothrow=true)
71
*/
72
function which(cmd, options);
73
```
74
75
### Sync Executable Search
76
77
Synchronously searches for executable in PATH environment variable.
78
79
```javascript { .api }
80
/**
81
* Synchronously find the first instance of an executable in PATH
82
* @param {string} cmd - Name of the executable to find
83
* @param {Object} [options] - Configuration options
84
* @param {string} [options.path] - Override PATH environment variable
85
* @param {string} [options.pathExt] - Override PATHEXT environment variable (Windows)
86
* @param {string} [options.delimiter] - Override path delimiter
87
* @param {boolean} [options.all=false] - Return all matches instead of just the first
88
* @param {boolean} [options.nothrow=false] - Return null instead of throwing when not found
89
* @returns {string|string[]|null} Path to executable, array of paths (if all=true), or null (if nothrow=true and not found)
90
* @throws {Error} Error with code 'ENOENT' if executable not found (unless nothrow=true)
91
*/
92
function whichSync(cmd, options);
93
```
94
95
### CLI Interface
96
97
Command-line interface that mimics BSD which(1) behavior.
98
99
```bash
100
# Basic usage
101
node-which program1 program2 ...
102
103
# Find all matches
104
node-which -a program
105
106
# Silent mode (no output)
107
node-which -s program
108
109
# Combined flags
110
node-which -as program
111
112
# End of options
113
node-which program -- --anything-goes-here
114
```
115
116
**CLI Options:**
117
- `-a`: Find all matches instead of just the first
118
- `-s`: Silent mode, suppress output
119
- `--`: End of options marker
120
121
**Exit Codes:**
122
- `0`: Success (all requested executables found)
123
- `1`: Failure (one or more executables not found, or usage error)
124
125
## Advanced Usage Examples
126
127
### Find All Matches
128
129
```javascript
130
const which = require('which');
131
132
// Find all instances of an executable
133
const allPaths = await which('node', { all: true });
134
console.log('All node installations:', allPaths);
135
// Output: ['/usr/bin/node', '/usr/local/bin/node', ...]
136
```
137
138
### Custom PATH
139
140
```javascript
141
const which = require('which');
142
143
// Search in custom PATH
144
const customPath = '/custom/bin:/another/path';
145
const result = await which('myapp', {
146
path: customPath,
147
nothrow: true
148
});
149
150
if (result) {
151
console.log('Found myapp at:', result);
152
} else {
153
console.log('myapp not found in custom PATH');
154
}
155
```
156
157
### Windows PATHEXT Override
158
159
```javascript
160
const which = require('which');
161
162
// Windows: search for executables with custom extensions
163
const result = await which('script', {
164
pathExt: '.js;.py;.bat',
165
nothrow: true
166
});
167
```
168
169
### Relative and Absolute Paths
170
171
```javascript
172
const which = require('which');
173
174
// If command contains path separators, it's treated as a direct path
175
const absolutePath = await which('/usr/bin/node', { nothrow: true });
176
const relativePath = await which('./local-script.sh', { nothrow: true });
177
```
178
179
## Error Handling
180
181
The package throws structured errors when executables are not found:
182
183
```javascript
184
const which = require('which');
185
186
try {
187
const result = await which('nonexistent-program');
188
} catch (error) {
189
console.log(error.message); // "not found: nonexistent-program"
190
console.log(error.code); // "ENOENT"
191
}
192
193
// Alternatively, use nothrow option
194
const result = await which('nonexistent-program', { nothrow: true });
195
if (result === null) {
196
console.log('Program not found');
197
}
198
```
199
200
## Platform-Specific Behavior
201
202
### Windows
203
- Checks current working directory first in PATH search
204
- Uses PATHEXT environment variable for executable extensions
205
- Default extensions: `.EXE`, `.CMD`, `.BAT`, `.COM`
206
- Case-insensitive extension matching
207
- Supports quoted paths in PATH
208
209
### Unix/POSIX
210
- Does not check current working directory by default
211
- No file extension processing
212
- Relies on executable permission bit
213
- Case-sensitive path handling
214
215
## Types
216
217
```javascript { .api }
218
/**
219
* Configuration options for which function
220
*/
221
interface WhichOptions {
222
/** Override PATH environment variable */
223
path?: string;
224
/** Override PATHEXT environment variable (Windows only) */
225
pathExt?: string;
226
/** Override path delimiter (default: require('path').delimiter) */
227
delimiter?: string;
228
/** Return all matches instead of just the first (default: false) */
229
all?: boolean;
230
/** Return null instead of throwing when not found (default: false) */
231
nothrow?: boolean;
232
}
233
234
/**
235
* Error thrown when executable is not found
236
*/
237
interface WhichError extends Error {
238
/** Error message: "not found: <command>" */
239
message: string;
240
/** Error code: "ENOENT" */
241
code: 'ENOENT';
242
}
243
```