Как мне перебирать файлы в npm способом, который работает в Windows и Linux?

Я пытаюсь запустить одну команду (jshint) для нескольких файлов. Мой package.json содержит

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

Однако в Windows это плохо. В Windows синтаксис для итераций для нескольких файлов это

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

Есть ли простой, независимый от платформы способ запустить один скрипт npm (например, jshint) для нескольких файлов?

(Меня интересует общее решение. здесь ссылки на использование node-jslint вместо jshint, который поддерживает несколько файлов ... но IMO jshint >> jslint).


person ripper234    schedule 27.12.2016    source источник


Ответы (2)


Я также не знаю о независимом от платформы способе цикла в оболочке.

Однако независимое от платформы решение для запуска одного npm-скрипта для нескольких файлов с помощью jshint в соответствии с вашим примером:

  1. Используйте cli-glob, чтобы найти .js файлы.
  2. По конвейеру результаты / пути из шаблона подстановки в сценарий настраиваемого служебного узла.
  3. Then within the node script:
    1. Read the paths piped to stdin using nodes readline module.
    2. Создайте Array каждого пути и затем преобразуйте его в String.
    3. Запустите исполняемый файл jshint (включая String всех путей), используя узлы child_process.exec() module .

Хотя это решение не особенно простое, следующие суть демонстрируют этот процесс:


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 ';

Лично для этого сценария предпочтительнее установить его локально!


Несколько шаблонов подстановки

Приведенный вами пример включает несколько шаблонов глобусов.

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

Одним из ограничений cli-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"
},

Да уж, не особо лаконично - но работает!

person RobC    schedule 29.01.2017

Насколько мне известно, вы не можете зацикливаться в оболочке кроссплатформенным способом.

Однако вы можете использовать https://github.com/substack/catw и сделать что-то вроде этого:

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

catw будет расширять глобус (ы), не полагаясь на оболочку, и записывать файлы в стандартный вывод. jshint - будет читать из стандартного ввода. Труба (|) работает кроссплатформенная.

person RyanZim    schedule 31.12.2016