JSPM

  • ESM via JSPM
  • ES Module Entrypoint
  • Export Map
  • Keywords
  • License
  • Repository URL
  • TypeScript Types
  • README
  • Created
  • Published
  • Downloads 700
  • Score
    100M100P100Q97254F
  • License MIT

Package Exports

  • shellsync

This package does not declare an exports field, so the exports above have been automatically detected and optimized by JSPM instead. If any package subpath is missing, it is recommended to post an issue to the original package (shellsync) to support the "exports" field. If that is not possible, create a JSPM override to customize the exports field for this package.

Readme

shellsync

Synchronous shell scripting for Node.js and TypeScript.

  • Pragmatic: automate tasks using synchronous code, using familiar commands from the command line.
  • Powerful: use JavaScript or TypeScript functions, modules, libraries, and for constructs like try/catch/finally.
  • Robust: use uninterruptable sections and harden your code with standard testing frameworks and mocking.
  • Safe: avoid most Bash pitfalls and use automatic, safe variable escaping.

Usage

Use sh to synchronously run shell commands:

const sh = require("shellsync");
const filename = "file name with spaces.txt";
sh`cd /tmp`;
sh`cat ${filename}`; // read filename\ with\ spaces.txt

Note how the above uses ES6 tagged template literals, calling the sh function without parentheses. This makes the invocations slightly shorter and allows shellsync to safely escape any values passed to it.

Use sh, sh.array, or sh.json to capture values:

let v1 = sh`echo hello`;                 // set v1 to "hello"
let v2 = sh.array`lsof -t -i :8080`;     // set v2 to all process ids listening on port 8080
let v3 = sh.json`echo '{"foo": "bar"}'`; // set v3 to {"foo": "bar"}

Use sh.test to determine command success (by default, failure throws):

if (!sh.test`which node`) {
    throw new Error("Node is not on the path!");
}

The commands above only output what is written to stderr. Use sh.out to also print stdout, or use shh completely mute stdout and stderr:

const {shh} = require("shellsync");
shh`git init`;             // git init (no output printed)
sh.out`echo "SHOUTING!"`;  // print "SHOUTING!" to stdout

Safe variable escaping

"The vast majority of [shell scripting] pitfalls are in some way related to unquoted expansions" – Bash Pitfalls wiki

shellsync safely quotes variables automatically:

let filename = "filename with spaces.txt";
sh`echo "hello" > cat ${filename}`; // write to filename\ with\ spaces.txt

Use unquoted() to disable automatic quoting:

import {unquoted} from "shellsync";
let command2 = "sudo apt-get install foo";
sh`ls; ${unquoted(command2)}`; // ls; sudo apt-get install foo

Writing tests

"I find that writing unit tests actually increases my programming speed." – Martin Fowler

Test your shellsync scripts using mocking and standard testing frameworks such as Mocha or Jest.

Use sh.mock(pattern, command) to mock shell command using glob patterns. For example, use the pattern git log to mock any calls to git log, or use git * to mock all calls to git accross the board. If you have multiple mocks, the longest (most specific) matching pattern wins.

sh.restoreMocks() restores all mocked commands to the original shell command.

Example Mocha test:

const sh = require("shellsync");

it("mocks git status", () => {
    sh.mock("git status", `echo git status called`);
    assert.equal(sh`git status`, "git status called");
});

it("mocks arbitrary git command", () => {
    sh.mock("git *", `echo git command called: $1`);
    assert.equal(sh`git foo`, "git command called: foo");
});

// Restore all mocked commands
afterEach(() => sh.mockRestore());

Uninterruptable sections

Users can press Control-C in CLI programs, which means they can end scripts halfway any statement. That means they can leave a system in an undefined state. In Node.js, Control-C even ends a program ignoring any finally clauses that might be used for cleanup.

Use sh.handleSignals() for sections of code where these signals should be temporarily ignored:

sh.handleSignals(); // begin critical section

sh`command1`;
sh`command2`;
sh`command3`;
sh`command4`;

sh.handleSignalsEnd(); // end critical section

Note that sh.handleSignals() affects both shell and Node.js code. If you're concerned your program won't end until the heat death of the universe and need to offer Control-C as an early way out, you can also pass a timeout in milliseconds: sh.handleSignals({timeout: 3000}).

API

sh`command`: void

Execute a command, return stdout.

sh.test`command`: boolean

Execute a command, return true in case of success.

sh.array`command`: string[]

Execute a command, return stdout split by null characters (if found) or by newline characters. Use sh.options.fieldSeperator to pick a custom delimiter character.

sh.json`command`: any

Execute a command, parse the result as JSON.

sh.handleSignals({timeout = null}): void

Disable processing of SIGINT/TERM/QUIT signals. Optionally accepts a timeout in milliseconds

When invoked, any signals pending since the last invocation get processed.

sh.handleSignalsEnd(): void

Re-enable processing of SIGINT/TERM/QUIT signals.

When invoked, any signals pending since the last invocation get processed.

sh.mock(pattern, [command]): void

Define a mock: instead of pattern, run command. Patterns consist of one or more words and support globbing from the second word, e.g. git, git status, git s*. The longest (most specific) pattern is used in case multiple mocks are defined.

sh.mockRestore(): void

Remove all mocks.

sh.quote`command`: string

Similar to sh, but return the command that would be executed.

sh.unquoted(...args): UnquotedPart

Create an unquoted part of a command template.

sh.options: SpawnSyncOptions

See the options for child_process.

sh.options.debug: boolean

Run in debug mode, printing commands that are executed.

sh.options.fieldSeperator: string

The delimiter used for sh.array.

sh(options): Shell

Return a shell with specific options assigned. See sh.options. Example use:

const input = "some text to write to a file";
sh({input})`cat > file.txt`;

shh`command`: string

Same as sh.val; doesn't print anything to stdout or stderr.

License

MIT.

See also

  • shell-tag - Run shell commands with template strings
  • shell-escape-tag - Run shell commands with template strings and control over escaping
  • any-shell-escape - Escape shell commands
  • shelljs - Portable implementation of Unix shell commands such as echo and grep