节点 - 检查路径中命令的存在

21

我面临一个独特的问题,需要使用Node迭代几个类Unix命令,并查看它们是否存在于Windows安装的

例如,Windows不支持ls。 但是,假设有人安装了git并选中包含Unix命令,则可以使用ls。

我需要知道系统

目前,我正在使用child_process在每个命令上运行帮助(help)。 然后检查运行它的响应。 这非常混乱且危险。 我不想从Node运行30个任意命令:

var spawnSync = require('child_process').spawnSync;
var out = spawnSync('ls', ['/?'], {encoding: 'utf8'});

我还能用什么方式检查这些命令是否存在?


@adeneo 嗯 - 我刚检查了我的Ubuntu安装,它默认没有这个。也许有些有,但这是一个Node安装程序包的一部分,必须在99.99999%的所有操作系统上工作。 - dthree
@adeneo 我可以知道我正在使用哪个操作系统:require('os').platform().indexOf('win') > -1 在 Node 中可行。 - dthree
2
哎呀,Windows 有 where,Ubuntu 则有 whereis,同样的东西,不同的名称。再次强调,没有一种方法适用于所有情况。 - adeneo
好的,你想把那个作为答案吗?我会接受它。 - dthree
请注意,它并不真正检查命令,而是可执行文件,例如 where dir 不起作用,但 where cmd 起作用,因为后者是一个可在 Windows 等全局调用的可执行文件 (cmd.exe)。如果有人将 ls 添加到 Windows 中,他们肯定添加了一个可执行文件,所以理论上应该可以工作? - adeneo
显示剩余7条评论
6个回答

20

个人而言,我发现在npm上的command-exists模块非常好用。

安装方法

npm install command-exists

使用方法

  • async

    var commandExists = require('command-exists');
    
    commandExists('ls', function(err, commandExists) {
    
        if(commandExists) {
            // proceed confidently knowing this command is available
        }
    
    });
    
  • promise

    var commandExists = require('command-exists');
    
    // invoked without a callback, it returns a promise
    commandExists('ls')
    .then(function(command){
        // proceed
    }).catch(function(){
        // command doesn't exist
    });
    
  • sync

    var commandExistsSync = require('command-exists').sync;
    // returns true/false; doesn't throw
    if (commandExistsSync('ls')) {
        // proceed
    } else {
        // ...
    }
    

对于 Windows 命令,是否需要添加 .exe 后缀?像这样:commandExists('curl.exe', function(err, commandExists) {...} ? - Abel Callejo
如果您传递的可执行文件位于调用此代码的目录中,则此函数也会返回true。不太确定是否应该这样做。例如,node ~/dev/that-code.js ./script 应该返回false,因为它不在PATH中。而 node ~/dev/that-code.js npm 应该返回true,因为npm在PATH中。 - Paul Sender

13

你可以在Linux中使用whereis命令,在Windows中使用where命令,查看可执行文件是否能被找到。

var isWin = require('os').platform().indexOf('win') > -1;

var where = isWin ? 'where' : 'whereis';

var spawn = require('child_process').spawn;

var out = spawn(where + ' ls', ['/?'], {encoding: 'utf8'});

out.on('close', function (code) {
    console.log('exit code : ' + code);
});

在 Mac OS 上,whereis 似乎无法定位 /usr/local/bin 中的命令(该路径已包含在我的 PATH 环境变量中)。但是 which 命令可以。 - ffxsam
编辑答案以包括Mac OS。 - ffxsam
我在macOS上遇到了一个错误 Error: spawn where ls ENOENT - loretoparisi
@loretoparisi - ENOENT 意味着没有这样的文件或目录,正如上面的注释所说,whereis 在 MacOS 上无法找到命令,你需要以某种方式包括 which - adeneo
在Windows PowerShell中,where命令无法使用,请改用where.exe或者gcmGet-Command的别名)。 - LitileXueZha

5
请勿仅为此而使用child_process,也不要使用内部使用child_process的软件包。正如Matt已经回答的那样,最简单的方法就是在您的Path下检查。
这里有一个NPM lookpath软件包,可扫描您的$PATH$Path
const { lookpath } = require('lookpath');

const p = await lookpath('bash');
// "/bin/bash"

这是一个来自Go的exec.LookPath的Node.js端口。
希望能够帮到你。

2

1

你能否在路径目录中检查一下,看看ls命令文件是否存在。

如果文件不存在于目录中,则不在路径中。


我想我可以遍历所有路径,但那似乎有点低效。希望能有更好的解决方案,但我会记在心里的。 - dthree
@dthree 相比于生成子进程,遍历 PATH 更有效率。我实现了一个 NPM 来做这件事 https://www.npmjs.com/package/lookpath 有关更多信息,请参见 https://dev59.com/jVsW5IYBdhLWcg3wdXCT#56321089。谢谢。 - otiai10

1
这里提供了不同shell的解决方案:

https://mywiki.wooledge.org/BashFAQ/081

例如,对于bash:

# Bash
if hash qwerty 2>/dev/null; then
  echo qwerty exists
else
  echo qwerty does not exist
fi

同时交叉参考:https://unix.stackexchange.com/questions/4988/how-do-i-test-to-see-if-an-application-exists-in-path - P i

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接