Google ZX - The Shell Alternative for Complex Scripts

Published: Posted by Patrick Henninger

When it comes to executing complex scripts that require accessing the output of other shell commands or analyzing data structures like arrays, the standard shell scripting language Bash quickly hits its limits. This is where Google ZX comes in, an open-source tool developed under the umbrella of the Google GitHub organization that allows you to write shell commands in JavaScript or TypeScript to perform complex tasks that are typically executed in the shell environment.

What is Google ZX?

Google ZX is a tool that allows you to write shell commands in JavaScript or TypeScript to perform complex tasks that are typically executed in the shell environment. It is provided as a Node.js module and can be executed in the command line.

With Google ZX, you can use JavaScript or TypeScript code to execute shell commands while also accessing features such as reading environment variables or parsing JSON files. This allows you to write scripts that combine the advantages of shell programming and JavaScript or TypeScript syntax.

Advantages of Google ZX over Bash

When it comes to complex scripts and data structures such as arrays, Google ZX has several advantages over Bash. Here are some of the advantages of ZX compared to Bash:

  1. Easy handling of data structures such as arrays
    In Bash, arrays can be used, but the syntax for working with arrays is complex and unwieldy. With Google ZX, on the other hand, you can simply use JavaScript or TypeScript code to create, iterate, and manipulate arrays, greatly simplifying the handling of data structures such as arrays.
  2. Access to the power of Node.js
    Since Google ZX is provided as a Node.js module, you have access to the power of Node.js. This means that you can use features such as asynchronous execution of shell commands and parallel processing of tasks to improve the performance of your scripts.
  3. Readable and maintainable code
    Since you can write complex scripts with Google ZX in JavaScript or TypeScript syntax, it can be easier for many developers to read and maintain the code compared to the more complex syntax of Bash.
  4. Easier error handling
    Error handling in complex scripts can be difficult in Bash. With Google ZX, however, you can access the error handling capabilities of JavaScript or TypeScript to ensure that your script runs smoothly and without issues.
  5. String escaping
    When dealing with nested data structures, various types of user input and text, and subshells, escaping data in Bash can quickly become cumbersome. Fortunately, Google ZX provides an out-of-the-box solution for string escaping. Take a look at the following example:
#!/usr/bin/env zx  
const input = 'This is my "string" with SPEC|AL Characters'  
$`echo ${input}`  

Example

Bash

#!/usr/bin/env bash

Create an array
arr=( "apple" "banana" "cherry" )

Print the length of the array
echo "The length of the array is ${#arr[@]}"

Print all elements of the array
echo "All elements of the array are: ${arr[@]}"

Loop through the array using a for loop
echo "Looping through the array using a for loop:"
for i in "${arr[@]}"; do
    echo $i
done

Google ZX

#!/usr/bin/env zx

// Create an array
const arr = ["apple", "banana", "cherry"];

// Print the length of the array
console.log(The length of the array is ${arr.length});

// Print all elements of the array
console.log(All elements of the array are: ${arr});

// Loop through the array using a for-of loop
console.log("Looping through the array using a for-of loop:");
for (const element of arr) {
    console.log(element);
}

As you can see, the syntax and usage of arrays in ZX are simpler and more readable compared to Bash. In ZX, you can simply declare an array variable and get the length of the array using the .length method. Looping through the array is done using a for-of loop, which is easier to read and write compared to the Bash for loop.

Error handling

While error handling in Bash is generally straightforward, it can become more complex when working with variables and functions. In some cases, a function may return either a value or an error message and exit with a non-zero status code. Since both the expected output as well as the error message are "return values", it is necessary to manually handle the exit code and re-echo the error message like in the following example:

#!/usr/bin/env bash

# Define the function
my_function() {
  local VAR="$1"
  if [ -z "$VAR" ]; then
    echo "This is the error information message. Something went wrong"
    exit 1
  fi
  echo "MyValue"
}

# Call the function and capture its output in a variable
output=$(my_function "some_input")

# Check the exit code of the function
if [ $? -eq 0 ]; then
  echo "Function succeeded with output: $output"
else
  echo "Function failed with exit code: $?"
  echo "Error information: $output"
fi

**You will also always have to keep in mind that defining a new variable in bash does return exit code 0 itself.

In Google ZX, you can handle exit codes and errors directly using the $ function. The $ function returns a promise that resolves with the standard output of the command, or rejects with an object that contains the exit code, standard error, and the original command string.

To handle errors and exit codes, you can use the standard JavaScript try/catch block. Here's an example with Google ZX:

#!/usr/bin/env zx  

try {
  const output = await $`command arg1 arg2`;
  console.log(`Output: ${output}`);
} catch (err) {
  console.error(`Error: ${err.message}`);
  console.error(`Exit code: ${err.exitCode}`);
  console.error(`Standard error: ${err.stderr}`);
  console.error(`Command: ${err.originalCommand}`);
}

In this example, the try block executes the command using the $ function and assigns the standard output to the output variable. If an error occurs, the catch block catches the error and logs information about the error, including the exit code, standard error, and the original command string.

Conclusion

When it comes to executing complex scripts that require accessing the output of other shell commands or analyzing data structures such as arrays, the standard shell scripting language Bash quickly hits its limits. This is where Google ZX comes in, an open-source tool developed by Google that allows you to write shell commands in JavaScript or TypeScript to perform complex tasks that are typically executed in the shell environment.

Overall, Google ZX provides a powerful alternative to Bash for developers who need to execute complex scripts. If you are familiar with JavaScript or TypeScript, using Google ZX can be an effective way to quickly and easily write complex shell scripts without having to deal with the complex syntax of Bash.