能用js实现的最终用js实现,Shell脚本也不例外

2,109 阅读4分钟

大家好,我是秋风。

今天来讨论一个牛逼的项目 ——zx ,1个月增长15000 star, 成为了2021年度明星项目排行榜第一。

图片

图片

zx 到底是什么呢?

我们可以从官网的介绍看到,一个能更方便地写脚本的工具。(A tool for writing better scripts)

Bash is great, but when it comes to writing scripts, people usually choose a more convenient programming language. JavaScript is a perfect choice, but standard Node.js library requires additional hassle before using. The zx package provides useful wrappers around child_process, escapes arguments and gives sensible defaults.

翻译:

Bash 用来写脚本非常棒,但是大家通常还是会去选择一种更方便方式去编写脚本,例如使用像 JavaScript 这种编程语言。但是 Node.js 在使用之前需要很多额外的操作,比如装包、引库等。但是zx 提供更多便捷的功能并且还对 child_process 进行了简化封装,从而能够直接调用一些命令。

通过阅读摘要和描述,我们可以知道虽然 Bash 很棒,但是没有 Node.js 简单。虽然 Node.js 编写起来简单,但是在使用前还是有一些麻烦的操作。而zx 没有以上两种方式的缺点,能够化繁为简,提供简单又方便操作。

在继续深入了解 zx 前,我们先来屡清楚目前提到的一些概念,了解这些概念有助于我们更好地去写脚本。

Shell、Shell脚本、Bash、zx、Node

首先来说说什么是Shell,Shell的中文意思是贝壳,是指与操作内核连接的外壳。

图片

狭义的Shell指的是命令行方面的软件,大多指Bash(Bash全称为 Bourne Again SHell ,是linux标准的默认Shell,它基于Bourne Shell,吸收了C Shell和Korn Shell );广义的Shell则包括图形界面。

因此 Shell 是一个大概念,包含了 Bash 等这些命令行工具,而利用这些工具写的脚本叫做Shell 脚本;而 Node 属于编程语言,可以编写 js 文件来执行一些命令, zx 是基于 Node 开发的工具,因此也能通过编写脚本来执行命令。

他们之间的关系我用一张图进行了描述,标题的概念用红色字样进行了加重。

图片

脚本可以做那些事情?

最为简单的就是重复的事情、处理数据格式,数据导入导出以及各种简单常用小工具的制作,环境配置等等。

举一些具体的例子就是:

下载视频

www.jianshu.com/p/0a013fa5a…

图片

下载音乐

图片

binaryify.github.io/NeteaseClou…

统计字数

图片

geek-docs.com/shell/shell…

自动签到

图片

github.com/RWoxiN/Qian…

...

功能太多了列举不过来,反正你会的操作能帮你简化,你不会的操作能帮你实现。

哪些人可以使用?

脚本不仅仅可以帮助开发人员还能帮助非开发人员

例如很多人都喜欢在个人博客上面写文章,这时就可以用WordPress 快速搭建一个博客,然后我们就用脚本一键来安装WordPress,下面以 Shell 脚本为例:

图片

gist.github.com/dessibelle/…

zx、Node、Shell(Bash) 功能评测

上面聊了脚本的一些概念以及脚本能帮助我们做什么。那么既然脚本这么强大,且脚本种类也非常多,为什么 zx 一经推出就这么收欢迎呢?

我们就以实际的功能为例来体验一下,分别使用了zx、Node、Shell(Bash,以下都称作Bash )三种脚本写一个批量压缩音视频的脚本

实现一个音频功能主要分成四个步骤

1.遍历当前目录

2.判断当前文件类型

3.执行压缩音频视脚本

首先我们先来看遍历当前目录三种脚本的写法:

Bash

#!bin/bash
for file in `(ls)`;
do
    ...
done

Node

import fs from 'fs';

const dirs = fs.readdirSync('./'));
for (let i in dirs) {
   ... 
}

zx

const dirs = (await $`ls`).stdout.split('\n')

for (let i in dirs) {
  ...
}

可以看到 Bash 和 zx 差不多,但是 zx 比Node 省去了引包的代码。

优势:zx = Bash > Node

其次我们再来看判断当前文件类型三种脚本的写法:

Bash

if test -f $file
then
    filename=$(basename $file);
    if [ "${file##*.}"x = "mp4"x ];then
        
    fi

    if [ "${file##*.}"x = "mp3"x ]; then

    fi
fi

Node、zx

if (dirs[i] && !fs.statSync(source).isDirectory()) { 
    if (source.endsWith(".mp4")) {
        
    }
    if (source.endsWith(".mp3")) {
        
    }
}

用Shell 来写整体上代码都非常的精炼,但是对于不经常使用的人来说,常常会遇到一些问题,例如 if 语句格式非常严格、判断比较的方式比较特殊、字符串操作都比较麻烦。

优势 Node = zx > Bash

最后再来执行压缩音频视脚本

Bash

...
ffmpeg -i $file -r 30 -c copy -c:v libx264 -vf scale=720:-2 "${filename%%.*}-30-720".mp4;
...

Node

const { spawn } = require('child_process');

function run(command) {
    return new Promise((rev, rej) => {
        console.log(command);
        const cmd = spawn(command.slice(01)[0], command.slice(1));

        cmd.stdout.on('data'(data) => {
          console.log(`stdout: ${data}`);
        });
        
        cmd.stderr.on('data'(data) => {
          console.error(`stderr: ${data}`);
        });
        
        cmd.on('close'(code) => {
            console.log(`child process exited with code ${code}`);
            rev();
        });
    })
}

...
await run(["ffmpeg""-i", source ,"-r","30","-c""copy","-c:v""libx264",  "-vf""scale=720:-2"`${dirs[i].replace('.mp4''')}-30-720.mp4`]);
...

zx

$`ffmpeg -i ${file} -r 30 -c copy -c:v libx264 -vf scale=720:-2 ${file.replace(".mp4","")}-30-720.mp4;`;

用 zx 可以做到和 Shell 一样的精简,利用内置的一些 Node 包使得整体的代码量大大下降。Node需要写一些额外的代码,例如执行命令run等等。

优势 Bash = zx > Node

上手程度代码复杂度
Shell简洁
Node简单繁琐
zx简单简洁

zx 上手体验非常好,可以说用四个字来概括, “简洁易用”,至此你是否对 zx 心动了呢?