能用js實現的最終用js實現,Shell指令碼也不例外

程式設計師秋風發表於2022-01-17

大家好,我是秋風。

今天來討論一個牛逼的專案 ——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 開發的工具,因此也能通過編寫指令碼來執行命令。

他們之間的關係我用一張圖進行了描述,標題的概念用紅色字樣進行了加重。

圖片

指令碼可以做那些事情?

最為簡單的就是重複的事情、處理資料格式,資料匯入匯出以及各種簡單常用小工具的製作,環境配置等等。

舉一些具體的例子就是:

下載視訊

https://www.jianshu.com/p/0a0...

圖片

下載音樂

圖片

https://binaryify.github.io/N...

統計字數

圖片

https://geek-docs.com/shell/s...

自動簽到

圖片

https://github.com/RWoxiN/Qia...

...

功能太多了列舉不過來,反正你會的操作能幫你簡化,你不會的操作能幫你實現。

哪些人可以使用?

指令碼不僅僅可以幫助開發人員還能幫助非開發人員

例如很多人都喜歡在個人部落格上面寫文章,這時就可以用WordPress 快速搭建一個部落格,然後我們就用指令碼一鍵來安裝WordPress,下面以 Shell 指令碼為例:

圖片

https://gist.github.com/dessi...

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(0, 1)[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 心動了呢?

相關文章