Nim: Executing external commands

Mar 21, 2022

One fairly unique aspect of executing commands that Nim has, that I've not experienced anywhere else, is staticExec. It allows a process to be executed at compile time, and the results at that specific moment included in the build in some way. An example from the docs is to interrogate the current environment to tag the current git status and OS architectures:

// Runs at compile time
const buildInfo = "Revision " & staticExec("git rev-parse HEAD") &
                  "\nCompiled on " & staticExec("uname -v")

To execute a process and return the results to a variable:

let output = execProcess("nim", args=["c", "-r", "hellowworld.nim"])

If you just want the exit status:

import osproc
let output = execCmd("blerk")
echo output
# sh: blerk: not found
# 127

Or if you want exit status and output:

import osproc

let (output, status) = execCmdEx("ls -a")
echo status
# 0
echo output
# . .. 

If you need to get more control then startProcess is the lower level function to call. The execProcess function earlier was just a convenience function to make common usage simpler. Make sure to close the process when you're done:

import osproc, strutils, streams

let process = startProcess("some-interactive-process", args = ["-v"],
  options = {poInteractive, poUsePath})
let (fromp, top) = (process.outputStream, process.inputStream)

top.write "repeat this please\n"
echo fromp.readLine.toUpper

top.write "and this\n"
echo fromp.readLine.toUpper

discard process.waitForExit
Hi, I'm Glenn! 👋 I'm currently Director of Product (Terraform) @ HashiCorp, and we're hiring! If you'd like to come and work with me and help make Terraform Cloud even more amazing we have multiple positions opening in Product ManagementDesign, and Engineering & Engineering Management across a range of levels (i.e., junior through to senior). Please send in an application ASAP so we can get in touch.