GitHub - txthinking/jb: jb: write script in an easier way than bash (original) (raw)

jb = javascript + bash

#!/usr/bin/env jb

$`ls -l`

var output = $1`whoami` <span class="katex"><span class="katex-mathml"><math xmlns="http://www.w3.org/1998/Math/MathML"><semantics><mrow><mo stretchy="false">(</mo><mi mathvariant="normal">‘</mi><mi>e</mi><mi>c</mi><mi>h</mi><mi>o</mi></mrow><annotation encoding="application/x-tex">(`echo </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">‘</span><span class="mord mathnormal">ec</span><span class="mord mathnormal">h</span><span class="mord mathnormal">o</span></span></span></span>{output}`)

Bash is great, but when it comes to writing more complex scripts, many people prefer a more convenient programming language. JavaScript is a perfect choice. The jb provides useful wrappers. The jb is a bun port of zx, the advantage is that you don't need to install node, and jb is just a standalone binary.

Install

jb is just a standalone binary, so you can download and put it in your PATH. Or install it via nami

Documentation

Just write your scripts in a file with an .js

Add the following shebang to the beginning of your jb scripts:

Now you will be able to run your script like so:

chmod +x ./script.js ./script.js

Or via the jb executable:

Or executes remote script

jb https://www.txthinking.com/script.js

All functions ($, cd, fetch, etc) are available straight away without any imports.

$`command`

Executes a given command, keep the default behavior of stdout and stderr like bash

Or put a variable in command

var name = 'hello' (‘mkdir(mkdir </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">‘</span><span class="mord mathnormal" style="margin-right:0.03148em;">mk</span><span class="mord mathnormal">d</span><span class="mord mathnormal">i</span><span class="mord mathnormal" style="margin-right:0.02778em;">r</span></span></span></span>{name})

You can pass an array of arguments if needed:

var flags = [ '-l', '-h', ] (‘ls(ls </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">‘</span><span class="mord mathnormal" style="margin-right:0.01968em;">l</span><span class="mord mathnormal">s</span></span></span></span>{flags.join(' ')})

If the executed program failed, error will be thrown.

$brook unknownsubcommand

$1`command`

Same as $`command` , but will return stdout and trim space, as you know, 1 is STDOUT

var count = $1ls -l | wc -l (‘echo(echo </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:1em;vertical-align:-0.25em;"></span><span class="mopen">(</span><span class="mord">‘</span><span class="mord mathnormal">ec</span><span class="mord mathnormal">h</span><span class="mord mathnormal">o</span></span></span></span>{count})

env()

Set env

env('HELLO', "JB") ‘echoecho </annotation></semantics></math></span><span class="katex-html" aria-hidden="true"><span class="base"><span class="strut" style="height:0.6944em;"></span><span class="mord">‘</span><span class="mord mathnormal">ec</span><span class="mord mathnormal">h</span><span class="mord mathnormal">o</span></span></span></span>HELLO // => JB

cd()

Changes the current working directory.

cd('/tmp') $pwd // => /tmp

question()

var name = question('What is your name? ')

confirm()

var ok = confirm('Do you really want to leave?');

sleep()

now()

Current unix timestamp

echo()

A console.log() alternative

which()

File path or null

exit()

Exit the script

exists_file()

file exists or not

var yn = exists_file('path/to/file.txt')

read_file()

Read the text from local file

var str = read_file('path/to/file.txt')

write_file()

Write text to local file

write_file('path/to/file.txt', 'some text')

append_file()

Append text to local file

append_file('path/to/file.txt', 'some text')

cp()

Copy file or http file from zip/tar.gz/tar.xz to local

cp('https://github.com/txthinking/brook/releases/latest/download/brook_darwin_arm64', '/tmp/brook');

Copy file from zip

7z l ~/Downloads/bun-darwin-aarch64.zip
   Date      Time    Attr         Size   Compressed  Name
------------------- ----- ------------ ------------  ------------------------
2023-06-03 15:54:41 D....            0            0  bun-darwin-aarch64
2023-06-03 15:54:41 .....     46584592     16787941  bun-darwin-aarch64/bun
------------------- ----- ------------ ------------  ------------------------
2023-06-03 15:54:41           46584592     16787941  1 files, 1 folders

cp('$HOME/Downloads/bun-darwin-aarch64.zip', 'bun-darwin-aarch64/bun', '/tmp/bun');

Copy multiple files from tar.gz

tar ztf ~/Downloads/cowsay_2.0.4_macOS_arm64.tar.gz
LICENSE
doc/cowsay.1
cowsay
cowthink

cp('$HOME/Downloads/cowsay_2.0.4_macOS_arm64.tar.gz', { 'cowsay': '/tmp/cowsay', 'cowthink': '/tmp/cowthink', });

Copy multiple files from tar.xz

tar Jtf ~/Downloads/shadowsocks-v1.15.3.aarch64-apple-darwin.tar.xz
sslocal
ssserver
ssurl
ssmanager
ssservice

cp('https://github.com/shadowsocks/shadowsocks-rust/releases/latest/download/shadowsocks-v1.15.3.aarch64-apple-darwin.tar.xz', { 'sslocal': '/tmp/sslocal', 'ssserver': '/tmp/ssserver', });

Async Functions

stdin()

Returns the stdin as a string.

var s = await stdin() echo(got ${s} from pipe);

echo hello | jb ./script.js

retry()

Will return after the first successful attempt, or will throw after specifies attempts count.

var s = await retry(() => $1curl https://www.txthinking.com)

// delay 1s var s = await retry(() => $1curl https://www.txthinking.com, 1000)

// delay 1s and max 3 times var s = await retry(() => $1curl https://www.txthinking.com, 1000, 3)

Web, Node, Bun

built-in Web API such as fetch

var res = await fetch('https://www.txthinking.com');

built-in node

import os from 'node:os';

echo(os.homedir());

built-in bun

Bun.serve({ port: 8080, hostname: '127.0.0.1', fetch(req) { return new Response("jb!"); }, });

Executing commands on remote hosts

The jb uses sshexec to execute commands on remote hosts.

$sshexec -s 1.2.3.4:22 -u user -p pass -c 'ls -l'

Download file from remote

$sshexec -s 1.2.3.4:22 -u user -p pass --download /server/path/to/file --to /local/path/to/file

Upload file to remote

$sshexec -s 1.2.3.4:22 -u user -k path/to/private/key --upload /local/path/to/file --to /server/path/to/file

License

jb itself is MIT-licensed. Refer to the dependencies license for information.