为什么使用 ShellJS
最近在做发版系统,需要在JS中执行 shell
,看了一些开源库,发现大部分都是选用了 shelljs
,发现这个工具用起来太爽了,它的npm周下载量达到了 5,998,285
,这足以能证明它的强大之处, 遂记录分享。
参考地址:https://www.npmjs.com/package/shelljs
快速体验
shell.exec 方法使用
我们以查找 git
命令所在目录为例:
const shell = require('shelljs');
const res = shell.exec('which scp');
console.log(res);
在这里,如果返回值的 code
属性为 0
,则表示找到了这个命令,其路径值存在属性stdout
中。如果返回值为 1
表示没有找到该命令。
shell.exec 方法类型
借助 VScode 可以找到 shell.exec
的类型:
export interface ExecFunction {
/**
* @desc 同步执行命令
* @param string 执行的命令
* @return 返回对象(包含code和output)
* code 为0表示操作正常, 为1表示操作异常
* output 实际的结果
*/
(command: string): ShellString;
/**
* @desc 同步执行命令
* @param string 执行的命令
* @param options 见 “理解 ShellJS 中的类型”
* @return 返回对象(包含code和output)
* code 为0表示操作正常, 为1表示操作异常
* output 实际的结果
*/
(command: string, options: ExecOptions & { async?: false }): ShellString;
/**
* 和上面差不多,但是时异步流程
*/
(
command: string,
options: ExecOptions & { async: true }
): child.ChildProcess;
/**
* 同步或者异步执行, 返回联合类型
*/
(command: string, options: ExecOptions): ShellString | child.ChildProcess;
/**
* 异步执行
*/
(
command: string,
options: ExecOptions,
callback: ExecCallback
): child.ChildProcess;
/**
* 异步执行
*/
(command: string, callback: ExecCallback): child.ChildProcess;
}
ShellJS 注意点
关于文件名通配符
shelljs 所有命令都支持标准的 bash
文件名通配符,比如:
?
匹配一个任意字符。*
匹配0个一个或多个任意字符。[]
匹配中括号中任意一个字符。[-]
匹配中括号中任意一个字符,- 代表范围。[^]
逻辑非,匹配不是中括号内的一个字符
同时 shelljs 兼容 node glob module
,详见 https://github.com/isaacs/node-glob。
源码 ExecOptions 接口
export interface ExecOptions extends child.ExecOptions {
/**
* Do not echo program output to the console.
* 不输出output到控制台
* @default false
*/
silent?: boolean;
/**
* Exit when command return code is non-zero.
* 当状态不为0时结束程序
* @default false
*/
fatal?: boolean;
/**
* Asynchronous execution.
* 是否异步执行
* If a callback is provided, it will be set to `true`, regardless of the passed value.
* 如果提供了回调函数,这个值会被设置为true,会忽略传进来的值
* @default false
*/
async?: boolean;
/**
* Character encoding to use.
* 设置输出的字符串编码
* Affects the values returned by `stdout` and `stderr`,
* and what is written to `stdout` and `stderr` when not in silent mode
* @default "utf8"
*/
encoding?: string;
}
快捷方法
如果每次执行 shell 命令都需要写 shelljs.exec(command)
,那么会让你觉得很繁琐,因此 shelljs 封装了对应的快捷操作命令,而且命令的可选参数通常放在第一位:
// 查看是否安装 git
if (!shell.which('git')) {
shell.echo('Sorry, this script requires git');
shell.exit(1);
}
// 文件复制
shell.rm('-rf', 'out/Release');
shell.cp('-R', 'stuff/', 'out/Release');
// 目录切换
shell.cd('lib');
shell.ls('*.js').forEach(function (file) {
shell.sed('-i', 'BUILD_VERSION', 'v0.1.2', file);
shell.sed('-i', /^.*REMOVE_THIS_LINE.*$/, '', file);
shell.sed('-i', /.*REPLACE_LINE_WITH_MACRO.*
/, shell.cat('macro.js'), file);
});
shell.cd('..');
API 列表
cat
const shell = require('shelljs');
// 把所有md文件全部内容组合起来, 返回新的字符串
var str = shell.cat('*.md');
console.log(str)
// 返回 test2.md 文件的内容
var str = shell.cat('test2.md');
console.log(str)
// 显示所有行号
var str = shell.cat("-n", 'test2.md');
console.log(str)
pwd
const shell = require('shelljs');
// 获取当前目录(执行命令的目录)
// process.cwd() 会返回相同的结果
const res = shell.pwd();
console.log(res)
未完待续...