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

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

首先,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 .. && mkdir test2,此时构建node代码如下:

var commands = [    'cd ..',    'mkdir test2',]
复制代码

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

当前目录:命令行当前所在路径。也是Node.js 进程的当前工作目录。

文件目录:脚本文档所在目录

两者不一样,比如你在系统根目录/执行了 node ./path/test/shell.js,那么当前目录就是/,文件目录就是./path/test/

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

var commands = [    'cd .. && 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} && ` + 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} && ` + 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)
    }

}
复制代码

是不是很简单呢?

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

码云笔记

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值