npm / node-which Goto Github PK
View Code? Open in Web Editor NEWLike which(1) unix command. Find the first instance of an executable in the PATH.
License: ISC License
Like which(1) unix command. Find the first instance of an executable in the PATH.
License: ISC License
The version on npm has the wrong line here:
if (isAbsolute(cmd)) return cb(null, cmd)
I'm using https://github.com/twilson63/express-coffee and the which command is broken on windows. The package.json appears correct in that project:
, "markdown": "0.4.0" , "passport": "0.1.15" , "which": "1.0.5" , "mongoose": "3.5.3"
Is it windows friendly?
I got reports that it didn't work right out of the box for the windows paths with spaces, e.g., "Program Files/..."
This is the proposed work around:
var node
node = which.sync('node')
// Surrounds with double quotes if path contains a space
if (node.indexOf(' ') != -1) {
node = '"' + node + '"'
}
If needed, I can submit a PR.
Somewhat self-explanatory, but this option exists for the which.sync and not which. It'd be nice to have it for both, and there doesn't seem to be anything inherently incompatible with the async implementation, just slightly messy.
The promise support introduced in 2.0.1 has a side-effect on the callback interface: the callback becomes part of the promise chain. If the callback throws, an unhandled promise rejection follows. With node's current default behavior (of not crashing) this is problematic.
Using which
>= 2.0.1 with the callback interface.
Line 84 in 8ef6069
which('foo', function () {
throw new Error('Something went wrong outside of the domain of `which`')
})
There are two possible solutions:
function example (callback) {
if (!callback) {
var promise = function (resolve, reject) {
callback = function (err, res) {
if (err) reject(err)
else resolve(res)
}
}
}
// ..
return promise
}
Would you take a PR for either?
I had this installed on my system without even realizing it (it's hidden somewhere in the dependency tree for taskbook), and it was causing tremendous, very difficult-to-debug delays in a separate, totally unrelated, non-Node program (GNU pass).
time which
was reporting 500ms for this utility compared to 3ms for GNU which on a 4th-gen Core i5 Linux box. For some reason, it runs very fast on a comparably specced machine I own. Happy to help debug, if you tell me what you need.
Please add changelog at least for major releases for breaking changes.
I noticed I couldn't install many npm packages because of:
npm ERR! not found: git
Digging deeper I noticed it's because of:
var pathEnv = opt.path || process.env.Path || process.env.PATH || ''
I have an env var on linux called Path
(because it's needed by wine), so that is what gets split
I guess it would be better to check for the env var appropriate for the detected OS instead.
npm ERR! fetch failed https://registry.npmjs.org/which/-/which-1.2.2.tgz
npm WARN retry will retry, error on last attempt: Error: fetch failed with status code 404
It seems the version has been removed?
The is-absolute
dep is still required and defined in the package.json
but is no longer being used.
According to the documentation for process.env, assigning an undefined variable to it, will implicitly convert the value to a string.
This behaviour can sometimes cause bugs in the tests due to the pathExt test saving an undefined value, then restoring it later, which later can cascade into the getPathInfo
function causing it to think that "undefined" is a valid file extension.
I'm having trouble reproducing this on master at the moment, but I'm currently writing a PR to fix #37, in which this bug is causing the tests to fail.
I got a bug report in cross-spawn-async
related to relative paths not working correctly. After investigation, which
changed handling of relative paths in 1.2.5
. The same test when using [email protected]
passes. As a workaround, if I do path.resolve
before calling which
it works correctly.
I will add a test case if necessary.
I have this:
foo/
test.js
package.json
node_modules/
.bin/
istanbul
in test.js I have:
const which = require('which');
var resolved = which.sync('istanbul');
console.log(resolved);
in package.json I have:
"dependencies": {
"istanbul": "^0.4.5",
"which": "^1.2.12"
},
I get this error in test.js
Error: not found: istanbul
at getNotFoundError (/home/olegzandr/Documents/WebstormProjects/suman-test-projects/subprojects/node-path-test/node_modules/which/which.js:13:12)
at Function.whichSync [as sync] (/home/olegzandr/Documents/WebstormProjects/suman-test-projects/subprojects/node-path-test/node_modules/which/which.js:131:9)
at Object.<anonymous> (/home/olegzandr/Documents/WebstormProjects/suman-test-projects/subprojects/node-path-test/test.js:7:22)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
at Module.runMain (module.js:605:10)
at run (bootstrap_node.js:420:7)
this seems to suggest that node-which does not pick up executables in ./node_modules/.bin
, ist das so?
When installing atom-beautify, Avira antivirus is picking up an HTML/ExpKit.Gen2 infection in the C:\Users\Name.atom.apm\registery.npmjs.org\which.cache.json file.
I suspect that it's Avira being over-sensitive but thought I'd pass it on.
Generally, the POSIX form command -v
is preferable to which
for the type of things this package does (which
is not part of POSIX). Debian has recently removed which
from the base distribution (see https://lists.debian.org/debian-devel/2021/09/msg00283.html), and while it was replaced, it now generates the diagnostic:
/usr/bin/which: this version of which is deprecated; use command -v in scripts instead.
Issues include which
's failure to canonicalize paths (sometimes)
Whenever which
is invoked from debianutils
, this diagnostic is annoyingly/worryingly generated. Whenever which
is invoked, unspecified behavior is risked.
The package invokes which
.
The package ought invoke command -v
. This might only be available as a builtin, in which case it can be invoked via invoking e.g. /bin/sh -c command -v
.
I'm happy to make this change for you if you agree that it ought be made. I do not see any reason to rename the module or change its API.
I am trying to get the path to Rscript
which runs R scripts from the command line using which function. I packaged the app using electron-packager (v15.2.0) in macOS Catalina (v10.15.7) and Ubuntu (v20.04). In Ubuntu, the app works perfectly before and after packaging i.e. in both development and production modes. However, in mac, it fails in the production mode. see the screenshots below.
I found Rscript can be executed from a Terminal (See screenshot below), so to me, it seems there are no issues related to executable not in path.
I'm wondering, why the npm function which
cannot detect Rscript
path in the production mode when it can discover it in the development mode? or is there a better way to get path that bypasses this problem?
The JS code to get the path is as follows:
'use strict'
const path = require("path");
const which = require("which");
const isDev = require('electron-is-dev');
if (isDev) {
console.log('Running in development');
} else {
console.log('Running in production');
}
which("Rscript", function (er, RscriptPath) {
console.log('RscriptPath = ' + RscriptPath);
})
Full source code to reproduce this issue can be obtained from this GitHub folder: https://github.com/wasimaftab/Utils/tree/master/Rscript_not_found
I tested using Electron v10.1.5 and v11.3.0
n/a
At the moment, the library does not find an executable specified with relative path. For example:
require('which')('./test/foo.sh', function(err) {
if (err) {
throw err;
}
})
ends up with "not found" error even if the file is there and has correct execution permissions. The same works fine on windows.
Standard Linux which utility works fine in such cases.
Is search order used in Linux which
utility is documented somewhere?
I am on macOS Sierra, running node 7.6.0 (installed via nvm). I find that when I run which
(this node module), I get the following error:
module.js:472
throw err;
^
Error: Cannot find module '../'
at Function.Module._resolveFilename (module.js:470:15)
at Function.Module._load (module.js:418:25)
at Module.require (module.js:498:17)
at require (internal/module.js:20:19)
at Object.<anonymous> (/Users/carter/Dev/node_modules/.bin/which:2:13)
at Module._compile (module.js:571:32)
at Object.Module._extensions..js (module.js:580:10)
at Module.load (module.js:488:32)
at tryModuleLoad (module.js:447:12)
at Function.Module._load (module.js:439:3)
If I update line 2 of node_modules/.bin/which
to instead be var which = require("../which")
then the script succeeds.
which
should be registered to PATH after installation.
npm i -g which
which which
and you will see something like above.Command returns not found
when everyone doesn't have execute
eg:
-rwxr-x--- 1 root webapps 463 Dec 13 12:18 compass
$ node node_modules/.bin/which compass
not found: compass
$ chmod 755 compass
$ node node_modules/.bin/which compass
/usr/local/bin/compass
version: 1.0.5
os: debian wheezy
On Windows, which()
always fails with TypeError: Object 0 has no method 'toLowerCase'
in the case when process.env.PATH
isn't defined (but process.env.Path
is).
Code was added in ff956d8 to deal with case sensitivity of environment variables under Windows, but there is a bug in this code path where p.toLowerCase()
should be k[p].toLowerCase()
(and process.env[p]
should also be changed accordingly).
// On windows, env.Path is common.
if (isWindows && !pathEnv) {
var k = Object.keys(process.env)
for (var p = 0; p < k.length; p++) {
if (p.toLowerCase() === 'path') {
pathEnv = process.env[p]
break
}
}
}
https://github.com/isaacs/node-which/blob/master/which.js#L46-L55
OS: Linux Mint 17 Qiana (kernel: 3.13.0-24-generic)
Node version: 6.11.0
npm version: 5.2.0
When I run npm i --save which
, I get:
npm WARN [email protected] No description
npm WARN [email protected] No repository field.
npm ERR! path /home/me/programming/foo/node_modules/which/bin/which
npm ERR! code ENOENT
npm ERR! errno -2
npm ERR! syscall chmod
npm ERR! enoent ENOENT: no such file or directory, chmod '/home/me/programming/foo/node_modules/which/bin/which'
npm ERR! enoent This is related to npm not being able to find a file.
npm ERR! enoent
npm ERR! A complete log of this run can be found in:
npm ERR! /home/me/.npm/_logs/2018-01-03T02_21_46_962Z-debug.log
Looking into ...-debug.log
gives nothing because at the end there is the same output.
On the other hand after I switched to Node 8.6.0, it hangs on:
[ ........] / extract:isexe: sill extract [email protected]
[ ........] / extract:isexe: sill extract [email protected]
[ ........] / extract:isexe: sill extract [email protected]
Versions 1.2.2 & 1.2.3 have suddenly disappeared from NPM. Please could you upload them again? Weirdly the versions
element within the XML doesn't include either version, but the time
element does include them https://registry.npmjs.org/which/.
I have two path entries 'D:....' but whichSync failed to iterate over pathEnv beyond these when trying to find the 'git' path. I changed the order so the 'D:...' entries were last and whichSync parsed everything up to but not including those moved 'D:...' entries. When moved, there were the 14th and 15th path entries.
It'd be great if which
supported the new Promises-based async syntax together with the more traditional callback-based async it currently has.
Example:
const which = require('which');
(async function() {
let path = await which('bash').catch(e => {
throw e;
});
console.log(e);
})();
I would be willing to send a (backwards-compatible) PR for this but I won't be able to until this weekend - I'm opening this first in case anyone is also interested/has remarks on the issue.
For my purposes, it would be more convenient if I could avoid having whichSync throw and instead ask it to return null if the executable is not found.
May I offer to make a PR for this?
I have tried to install node-which
on ubuntu 14.04. npm v3.10.6. node v6.8.1. But it always fails because it's no on npm registery!
Here is the logs:
vagrant@vagrant-ubuntu-trusty-64:~$ npm install node-which
npm ERR! Linux 3.13.0-92-generic
npm ERR! argv "/usr/bin/nodejs" "/usr/bin/npm" "install" "node-which"
npm ERR! node v6.8.1
npm ERR! npm v3.10.6
npm ERR! code E404
npm ERR! 404 Registry returned 404 for GET on https://registry.npmjs.org/node-which
npm ERR! 404
npm ERR! 404 'node-which' is not in the npm registry.
npm ERR! 404 You should bug the author to publish it (or use the name yourself!)
npm ERR! 404
npm ERR! 404 Note that you can also install from a
npm ERR! 404 tarball, folder, http url, or git url.
npm ERR! Please include the following file with any support request:
npm ERR! /home/vagrant/npm-debug.log
The most recent node-which npm does not install correctly with "npm install" for raspberry pi (arm 32). The resulting folder in node_modules is empty except from a "package.json" file when running node 12.0 and npm 6.10.3
Windows now features per-directory case-sensitivity. This is explained here: https://blogs.msdn.microsoft.com/commandline/2018/02/28/per-directory-case-sensitivity-and-wsl/
A directory created in the Windows Subsystem for Linux will be case-sensitive by default.
This library will read the PathExt
environment variable to find file extensions, and try appending them to the input path one-by-one until it finds a match. The file extensions listed in PathExt
are all upper-case.
As a result, the isexe
check will always return false when the file extension of the executable file is lower-case.
Just a heads up. It complains that graceful-fs can't be found.
In Git Bash on Windows 10
$ which esptool.py
/c/Python27/Scripts/esptool.py
c:/Python27/Scripts
is also added in PATH ENV.
But, the following code using which
module is failed.
var which = require('which');
var cmd = 'esptool.py';
try {
var ret = which.sync(cmd);
} catch (error) {
console.log('error', error);
}
console.log(ret);
$ node test.js
error { Error: not found: esptool.py
at getNotFoundError (C:\Users\Young\Desktop\test\node_modules\which\which.js:13:12)
at Function.whichSync [as sync] (C:\Users\Young\Desktop\test\node_modules\which\which.js:132:9)
at Object.<anonymous> (C:\Users\Young\Desktop\test\test.js:6:21)
at Module._compile (module.js:570:32)
at Object.Module._extensions..js (module.js:579:10)
at Module.load (module.js:487:32)
at tryModuleLoad (module.js:446:12)
at Function.Module._load (module.js:438:3)
at Module.runMain (module.js:604:10)
at run (bootstrap_node.js:393:7) code: 'ENOENT' }
undefined
What's wrong ???
When using /bin/sh
on windows (like with Cmder), the path separator in $PATH is :
not ;
so nothing is ever resolved unless it lives in the cwd
.
So because node-which
is used by pretty much every node tool, it causes a frustratingly large amount of problems for people who want to use a sane shell other than cmd.exe
, the primary being npm.
It boils down to this line:
https://github.com/isaacs/node-which/blob/master/which.js#L6
No documentation / sample on the README..
I tried something like this but didn't work
var which = require('which');
console.log(which.whichSync("git"));
which.which("git", function(err, path) {
console.log(path);
});
npx which openapi-typescript
is resulting in the error below:
'node-which' is not recognized as an internal or external command,
operable program or batch file.
I am executing in Windows 11, and tried in both powershell and git bash shells from VSCode terminal.
What is the issue?
Should be like that?
Example:
...\0.20.2\hugo.EXE
...\go1.8\bin\go.EXE
...\atom\bin\atom.CMD
^ this is console.log from my app. I didn't check CLI.
Edit:
I was trying to find source of problem in code of node-which.
Changing line 29 in which.js file did nothing.
pathExtExe = (opt.pathExt || process.env.PATHEXT || '.exe;.cmd;.bat;.com')
Edit:
I was playing more with that line 29.
It seems problem is related to process.env.PATHEXT
and probably to Windows OS.
My temporary fix for that is to change that line to look like this:
pathExtExe = (opt.pathExt || '.exe;.cmd;.bat;.com' || process.env.PATHEXT)
C:\>npm install -g which
C:\Users\%USER%\AppData\Roaming\npm\which -> C:\Users\%USER%\AppData\Roaming\npm\node_modules\which\bin\which
C:\Users\%USER%\AppData\Roaming\npm
└─┬ [email protected]
└─┬ [email protected]
└── [email protected]
C:\>which java
C:\>java -version
java version "1.8.0_40"
Java(TM) SE Runtime Environment (build 1.8.0_40-b25)
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode)
This is on windows 7 pro.
Am I missing something important about how this library operates? I'm attempting to install another module that uses which (selenium-standalone) and it's failing on a java check. I cannot for the life of me determine why, as I have it in my path (as demonstrated by my version check).
This test case just cannot ends with a positive result when -a
option is used on windows.
which
command by default, so it will not be found.bin/which
is not treated as an executable and will not be found.As the result output of bin/which
will contain contain zero (by default) or one (if a custom which
command is installed, ex. one from cygwin
) lines. It means that this check always fails.
May be we should use another target command for the check?
On 1.1.1, the following use case does not work:
require('which').sync('compass');
It would seem that the new logic treats command search as absolute path and therefore won't look in the pathenv
.
which
might fail to resolve the executable on Windows in a threaded context (e.g. a Worker threads) due to PATH
being undefined, instead being accessible (only) as Path
.
Prior work on this topic in this project exists, starting with #34. It suggests there used to be an alternative lookup, but it was removed for a different reason (as I understand it). The removal happened in #35 / c7a1ac9, stating that:
Reading from a Path environ on Unix systems sometimes causes strange behavior
which is too cryptic for me to understand 😅 Nevertheless, it seems like a fair concern so I think a solution to the problems should take it into account. I'd also like to point out that issues on the Node.js repository on this topic suggest PATH
being undefined is 1) known behavior, and 2) not considered a bug.
Running the reproducing script (see below) myself in various settings, I must admit I was not able to reproduce this issue with 100% accuracy. It somehow seems to depend on the terminal in which I run the script, in particular: I can reproduce it using the Windows terminal with both CMD and PowerShell (but not bash, coming with git for Windows) but not with any shell in the VSCode embedded terminal...
which
does not fail to resolve the executable on Windows if PATH
is undefined.
My suggestion would be to consider process.env.Path
when process.env.PATH
is undefined, possibly conditionally on whether which
is running on Windows (per c7a1ac9).
// file: repro.js
import * as process from "node:process";
import { Worker, isMainThread } from 'node:worker_threads';
if (isMainThread) {
console.log("[MAIN]", "PATH:", process.env.PATH);
new Worker("./repro.js");
} else {
console.log("[WORK]", "PATH:", process.env.PATH);
}
node repro.js
from PowerShell or CMD in Windows Terminal (Windows 11) or PowerShell/Command prompt (earlier Windows versions).[MAIN] PATH:
prints the full path but the [WORK] PATH:
is undefined.I suggest to add error code such as ENOENT
to not found errors. It could be useful for programmatic detection of what went wrong.
If the maintainers are interested in it I could provide a pull request.
Given multiple arguments, which
is supposed to print the location of each match, and return the number of errors as the exit code.
For example:
$ which ls mkdir
/bin/ls
/bin/mkdir
$ echo $?
0
$ which doesnotexist mkdir
/bin/mkdir
$ echo $?
1
However, this package doesn't behave that way:
$ node_modules/.bin/which ls mkdir
/bin/ls
$ echo $?
0
$ node_modules/.bin/which doesnotexist mkdir
not found: doesnotexist
$ echo $?
127
I ran into an issue where i had a directory in my path which contained a subdirectory. While using which to find an actual executable, it returned the path to the directory instead since it was first in the path:
➜ which ls -l
total 0
drwxr-xr-x 2 ptierno staff 68 Aug 25 19:02 directory
➜ which export PATH=`pwd`:$PATH
➜ which node
> var which = require('which');
undefined
>
> which.sync('directory')
'/Users/ptierno/which/directory'
If I remove the executable bit from the directory then the directory doesnt get returned (which is what I would expect).
➜ which chmod -x directory
➜ which node
> var which = require('which');
undefined
> which.sync('directory')
Error: not found: directory
at getNotFoundError (/Users/ptierno/node_modules/which/which.js:14:12)
at Function.whichSync [as sync] (/Users/ptierno/node_modules/which/which.js:132:9)
at repl:1:7
at REPLServer.defaultEval (repl.js:272:27)
at bound (domain.js:280:14)
at REPLServer.runBound [as eval] (domain.js:293:12)
at REPLServer.<anonymous> (repl.js:441:10)
at emitOne (events.js:101:20)
at REPLServer.emit (events.js:188:7)
at REPLServer.Interface._onLine (readline.js:224:10)
>
Might be a good idea to do a check to ensure the value being returned is an actual executable file and not a directory.
When on windows I get following errors from the which library.
gyp verb `which` failed Error: not found: python2
gyp verb `which` failed at getNotFoundError (C:\code\my_project\node_modules\which\which.js:13:12)
gyp verb `which` failed at F (C:\code\my_project\node_modules\which\which.js:68:19)
gyp verb `which` failed at E (C:\code\my_project\node_modules\which\which.js:80:29)
gyp verb `which` failed at C:\code\my_project\node_modules\which\which.js:89:16
gyp verb `which` failed at C:\code\my_project\node_modules\isexe\index.js:42:5
gyp verb `which` failed at C:\code\my_project\node_modules\isexe\windows.js:36:5
gyp verb `which` failed at FSReqWrap.oncomplete (fs.js:152:21)
gyp verb `which` failed python2 { Error: not found: python2
gyp verb `which` failed at getNotFoundError (C:\code\my_project\node_modules\which\which.js:13:12)
gyp verb `which` failed at F (C:\code\my_project\node_modules\which\which.js:68:19)
gyp verb `which` failed at E (C:\code\my_project\node_modules\which\which.js:80:29)
gyp verb `which` failed at C:\code\my_project\node_modules\which\which.js:89:16
gyp verb `which` failed at C:\code\my_project\node_modules\isexe\index.js:42:5
gyp verb `which` failed at C:\code\my_project\node_modules\isexe\windows.js:36:5
On windows in git bash it should though have paths like this.
gyp verb `which` failed Error: not found: python2
gyp verb `which` failed at getNotFoundError (/c/code/my_project/node_modules/which/which.js:13:12)
gyp verb `which` failed at F (/c/code/my_project/node_modules/which/which.js:68:19)
gyp verb `which` failed at E (/c/code/my_project/node_modules/which/which.js:80:29)
gyp verb `which` failed at /c/code/my_project/node_modules/which/which.js:89:16
gyp verb `which` failed at /c/code/my_project/node_modules/isexe/index.js:42:5
gyp verb `which` failed at /c/code/my_project/node_modules/isexe/windows.js:36:5
gyp verb `which` failed at FSReqWrap.oncomplete (fs.js:152:21)
gyp verb `which` failed python2 { Error: not found: python2
gyp verb `which` failed at getNotFoundError (/c/code/my_project/node_modules/which/which.js:13:12)
gyp verb `which` failed at F (/c/code/my_project/node_modules/which/which.js:68:19)
gyp verb `which` failed at E (/c/code/my_project/node_modules/which/which.js:80:29)
gyp verb `which` failed at /c/code/my_project/node_modules/which/which.js:89:16
gyp verb `which` failed at /c/code/my_project/node_modules/isexe/index.js:42:5
gyp verb `which` failed at /c/code/my_project/node_modules/isexe/windows.js:36:5
Steps to reproduce:
sudo chmod o-x /usr/bin/make
sudo chown root:sudo /usr/bin/make
node-gyp build
from a user who is a member of group sudo
, but sudo
is not his primary group(Tested on Debian 6.0.8)
node-gyp will complain about missing make
, even if make
is in fact executable by current user.
Some people experience RVM install failures on Travis and after longer investigation it has been proved that node-which is the source of the problem:
I am RVM maintainer and I am seeking for solution to this problem. Can you help?
canvas
and babel-istanbul
.which
command in a shell scriptwhich
module is run instead of the builtin command and the check fails.Output of the script with builtin (OSX 10.11.1):
true
Output of the script with which
module:
not found: ldconfig
true
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.