shelljs 前端自动化必备

为什么使用 ShellJS

最近在做发版系统,需要在JS中执行 shell,看了一些开源库,发现大部分都是选用了 shelljs,发现这个工具用起来太爽了,它的npm周下载量达到了 5,998,285,这足以能证明它的强大之处, 遂记录分享。

-w1257

参考地址:https://www.npmjs.com/package/shelljs

快速体验

shell.exec 方法使用

我们以查找 git 命令所在目录为例:

const shell = require('shelljs');

const res = shell.exec('which scp');
console.log(res);

-w959

在这里,如果返回值的 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.*\n/, 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)

未完待续...

posted on 2020-07-03 00:03  manbax  阅读(2986)  评论(0编辑  收藏  举报