zl程序教程

您现在的位置是:首页 >  Javascript

当前栏目

关于node代码如何丝滑执行多条命令行这件事

2023-02-18 16:43:02 时间

最近写脚本比较多,然后经常写命令行相关的代码,记录一下以备万一。

首先,node使用命令行依赖于child_process,这个是node原生支持的,我用的最多就是exec。

按顺序执行多个命令

因为写脚本需要执行多个语句,所以写了一个方法来执行,一个成功了,然后继续执行下一个。

const { exec } = require('child_process')
const util = require('util');
const execPromise = util.promisify(exec)

var commands = [
    'mkdir test',
    'mkdir test2',
]


execCommands(commands)
async function execCommands(commands) {
    let index = 0
    try {
        for (let i = 0; i < commands.length; i++) {
            index = i
            const command = commands[i];
            const res = await execPromise(command)
            console.log('exec command success', index, '[', commands[index], ']', '\n    value:', res)
        }
    } catch (error) {
        console.error('exec command fail at:', index, '[', commands[index], ']', '\n    error:', error)
    }

}

但是这样还有一个问题,那就是命令的执行位置,如果你使用cd命令,那么你第一想法可能是先进入那个目录,然后在该目录下执行命令。在cmd里面大概是这样cd .. &amp;&amp; mkdir test2,此时构建node代码如下:

var commands = [
    'cd ..',
    'mkdir test2',
]

但是实际执行结果却不太对,因为对于exec方法而言,每次路径都需要从当前目录开始算。

当前目录:命令行当前所在路径。也是Node.js 进程的当前工作目录。 文件目录:脚本文档所在目录 两者不一样,比如你在系统根目录/执行了 node ./path/test/shell.js,那么当前目录就是/,文件目录就是./path/test/

为了解决跨目录执行命令的问题,你可以

var commands = [
    'cd .. &amp;&amp; mkdir test2',
]

这是最简单的。

支持切换当前目录

但是试想每次你测试命令行语句都是在cmd终端里,如果每次都要比cmd里面多写一些cd命令,明显会耽误时间。达不到ctrl+c+v的丝滑感受。我既然写了这个文章那就不能不追求完美。

既然要改变当前目录,那么根据上面的经验,最简单的方法就是在每一个命令之前加cd。 但是这个cd怎么来呢?答案是,记录当前位置的绝对路径,然后通过算cd命令和当前目录。更改当前位置的绝对路径。当然因为记录了当前位置,cd命令不再执行。

让我们demo一下

let curAbsPath = process.cwd() // 获取当前目录
// blah blah blah

// 每次执行cd命令,不执行exec了
const cdCommand =  'cd ./demo'
curAbsPath = path.resolve(curAbsPath,cdCommand.replace('cd ',''))


// 每次执行非cd命令
let newCommand = `cd ${curAbsPath} &amp;&amp; ` + command
const res = execPromise(newCommand)

那么完整的代码如下:

const { exec } = require('child_process')
const util = require('util');
const path = require('path');
const execPromise = util.promisify(exec)


var commands = [
    'cd ../tripdocs-js-sdk',
    'mkdir test2',
    'mkdir test3',
]


execCommands(commands)
async function execCommands(commands) {
    let curAbsPath = process.cwd() // 获取当前目录
    let index = 0
    try {
        for (let i = 0; i < commands.length; i++) {
            index = i
            const command = commands[i];
            if (command.startsWith('cd ')) {
                // 每次执行cd命令,不执行exec了
                curAbsPath = path.resolve(curAbsPath, command.replace('cd ', ''))
                continue
            }
            // 每次执行非cd命令
            let newCommand = `cd ${curAbsPath} &amp;&amp; ` + command
            const res = await execPromise(newCommand)
            console.log('exec command success', index, '[', commands[index], ']', '\n    value:', res)
        }
    } catch (error) {
        console.error('exec command fail at:', index, '[', commands[index], ']', '\n    error:', error)
    }

}

是不是很简单呢?

我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=24rhz94mdo9w0