Jarred Sumner, CEO and founder of Bun, recently announced the release of Bun Shell, providing JavaScript and TypeScript developers with a cross-platform shell. This release aims to simplify the execution of shell scripts in JavaScript and TypeScript, providing a bash-like environment that delivers features such as globbing, environment variables, redirection, and piping. The release is alpha quality which could have breaking changes in the future.
Incorporating shell commands within Node.js hasn't always been straightforward for developers. While the child_process module is functional, it comes with security risks, particularly in handling unsanitized user input, and lacks ease of use. On the other hand, fs/promise module provides asynchronous file system operations, but it falls short as a direct substitute for common shell commands. To bridge this gap, the developer community has turned to packages such as shelljs and rimraf.
Bun Shell API introduces a range of features designed to enhance the scripting experience. Firstly, it ensures cross-platform compatibility, eliminating the need for additional dependencies when working on Windows, Linux, or macOS. Additionally, it adopts a bash-like environment, offering a familiar syntax that aligns with established conventions in shell scripting. Currently, it supports essential commands like "ls", "cd", and "rm" natively. The native support for glob patterns, including **, *, {expansion}, and more, enhances flexibility in command creation. Template literals in Bun Shell allow for the execution of shell commands with easy interpolation of variables and expressions. For security reasons, all strings are escaped by default, mitigating the risk of shell injection attacks.
Sumner emphasizes the versatility and features of Bun Shell, stating:
It works on Windows, macOS, and Linux. We've implemented many common commands and features like globbing, environment variables, redirection, piping, and more.
JavaScript interpolation is another notable feature, enabling the use of Response, ArrayBuffer, Blob, Bun.file(path), and other JavaScript objects such as stdin, stdout, and stderr. This integration allows it to work with diverse data types within scripts.
Starting with the basics, such as echoing a message, can be achieved with the $ template literal tag:
import { $ } from "bun";
await $`echo "Hello World!"`; // Hello World!
Accessing the output as text is straightforward using the .text() method:
import { $ } from "bun";
const result = await $`echo "Hello World!" | wc -w`.text();
console.log(result); // 2
In a Reddit thread discussing the recent announcement of Bun Shell's release, Reddit user u/nonlogin raised a question, asking,
How does it compare to zx?
In response, u/TheUnlocked highlighted the distinctions between Bun Shell and zx, stating,
It looks like Bun's version is a completely new shell that has similar syntax to bash (but is cross-platform and allows for neat things like redirecting into buffers), whereas zx is just an easier and safer way to invoke existing shells.