2

我正在尝试在多个文件上运行单个命令(jshint)。我的 package.json 包含

"lint": "jshint *.js **/*.js"

然而,这在 Windows 上失败得很惨。在 Windows 上,迭代多个文件的语法是

 for %%f in (*.in) do (
            echo %%~nf
    )

是否有一种简单的、与平台无关的方法来在多个文件上运行单个 npm 脚本(例如 jshint)?

(我对通用解决方案感兴趣。这里有一个使用node-jslint 而不是 jshint 的参考,它确实支持多个文件......但 IMO jshint >> jslint)。

4

2 回答 2

1

我也不知道在 shell 中循环的平台无关方式。

但是,根据您的示例,使用jshint在多个文件上运行单个npm-script的平台无关解决方案是:

  1. 利用cli-glob查找.js文件。
  2. 将结果/路径从 globbing 模式传输到自定义实用程序节点脚本。
  3. 然后在节点脚本中:
    1. stdin使用节点readline模块读取通过管道传输的路径。
    2. 创建Array每个路径的一个,然后将其转换为String.
    3. 使用节点模块运行jshint可执行文件(包括String所有路径) 。child_process.exec()

虽然这个解决方案不是特别“简单”,但以下要点展示了这个过程:


npm脚本

"scripts": {
    "jshint": "glob \"src/js/**/*.js\" | node .scripts/jshint.js"
},

注意 cli-glob添加到 package.json)获取路径并将它们通过管道传递给jshint.js


jshint.js

#!/usr/bin/env node

'use strict';

var path = require('path');
var readline = require('readline');
var exec = require('child_process').exec;

var rl = readline.createInterface({
    input: process.stdin,
    output: null,
    terminal: false
});

// Normalise path to local jshint executable.
var jshintExec = ['.', 'node_modules', '.bin', 'jshint '].join(path.sep);

var paths = [];

function jshint(paths) {
    var command = [jshintExec, paths].join('');
    exec(command, function(error, stdout, stderr) {
        if (stdout) {
            console.log(stdout);
        }
        if (stderr) {
            console.log(stderr);
        }
    });
}

rl.on('line', function(srcPath) {
    paths.push(srcPath);
});

rl.on('close', function() {
    jshint(paths.join(' '));
});

笔记

第 16 行阅读:

var jshintExec = ['.', 'node_modules', '.bin', 'jshint '].join(path.sep);

该脚本假定jshint已在本地安装并添加"devDependencies": {}package.json. 即它指向在文件夹jhint中找到的本地可执行node_modules/.bin文件,而不是全局安装的。

如果您的偏好是运行全局安装,jshint则将第 16 行更改为:

var jshintExec = 'jshint ';

就个人而言,在本地安装它是这种情况下的首选恕我直言!


多种通配模式

您提供的示例包括多个 glob 模式。

"lint": "jshint *.js **/*.js"

cli-glob的一个限制是它不接受多个 glob 模式。所以一种解决方法是做这样的事情:

"scripts": {
    "jshint": "npm run jshint-a && npm run jshint-b",
    "jshint-a": "glob \"*.js\" | node .scripts/jshint.js",
    "jshint-b": "glob \"**/*.js\" | node .scripts/jshint.js"
},

是的,不是特别简洁 - 但有效!

于 2017-01-29T15:20:06.643 回答
0

据我所知,您不能以跨平台的方式在 shell 中循环。

但是,您可以使用https://github.com/substack/catw并执行以下操作:

catw "**/*.js" | jshint - 

catw将在不依赖外壳的情况下扩展 glob 本身并将文件写入标准输出。jshint -将从标准输入读取。管道 ( |) 跨平台工作。

于 2016-12-31T14:42:52.543 回答