如何以适用于 Windows 和 linux 的方式遍历 npm 中的文件?

Posted

技术标签:

【中文标题】如何以适用于 Windows 和 linux 的方式遍历 npm 中的文件?【英文标题】:How do I loop through files in npm in a way that works on Windows & linux? 【发布时间】:2017-05-11 07:10:32 【问题描述】:

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

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

但是,这在 Windows 上失败得很惨。在 Windows 上,iterate on multiple files 的语法是

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

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

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

【问题讨论】:

【参考方案1】:

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

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

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

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


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 已在本地安装并添加到package.json"devDependencies": 部分。 IE。它指向在node_modules/.bin 文件夹中找到的本地jhint 可执行文件,而不是全局安装的。

如果您的偏好是运行全局安装的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"
,

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

【讨论】:

【参考方案2】:

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

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

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

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

【讨论】:

以上是关于如何以适用于 Windows 和 linux 的方式遍历 npm 中的文件?的主要内容,如果未能解决你的问题,请参考以下文章

无法弄清楚如何使用适用于 Linux 和 composer 的 Windows 子系统运行 box\Spout

如何在 c++ 中创建一个适用于 Windows 和 linux 的文件夹(目录)[重复]

如何使用 windows 下载适用于 linux 的 pip 模块

堆栈增长如何在 Windows 和 linux 上工作?

如何发布适用于 Windows 或 Mac 或 Linux 系统的 Electron 应用程序?

适用于 Linux 的 Windows 子系统安装指南 (Windows 10) (微软官方文档)