Calling Shell Commands from YAML
Wouldn't it be handy to get data from shell commands in YAML?
Well you can, and it's really easy.
YS has a bunch of functions in its Standard Library for calling shell commands, and passing data to and from them.
Let's take a look...
The shell
function🔗
When you just want to run a shell command and let its outputs print to the
terminal, you can use the shell
function.
$ ys - <<'...'
!YS-v0
shell: 'fortune'
...
You have taken yourself too seriously.
This is the same as running fortune
in from the command line.
You can also pass data to the shell command.
Let's try the tac
command, which reverses the lines of a file.
$ ys - <<'...'
!YS-v0
shell {:in "foo\nbar\nbaz\n"}: 'tac'
...
baz
bar
foo
The sh
function🔗
The sh
function doesn't print the output to the terminal.
It returns a mapping that contains a bunch of fields like the exit code, stdout,
stderr, and more.
$ ys - <<'...'
!YS-v0
result =:
sh: 'echo "Hello, World!"'
say: result.out
...
Hello, World!
Let's look at the entire result object:
$ ys - <<'...'
!YS-v0
result =:
sh: 'echo "Hello, World!"'
say: result
...
{:proc #object[java.lang.ProcessImpl 0x512d4b90 Process[pid=1364706, exitValue=0]], :exit 0, :in #object[java.lang.ProcessImpl$ProcessPipeOutputStream 0x22ebcf7e java.lang.ProcessImpl$ProcessPipeOutputStream@22ebcf7e], :out Hello, World!
, :err , :prev nil, :cmd [echo Hello, World!]}
That's kind of ugly and hard to read.
Let's use the yaml/dump
function to pretty print it:
$ ys - <<'...'
!YS-v0
result =:
sh: 'echo "Hello, World!"'
say: result:yaml/dump
...
proc: !!java.lang.ProcessImpl {}
exit: 0
in: !!java.lang.ProcessImpl$ProcessPipeOutputStream {}
out: |
Hello, World!
err: ''
prev: null
cmd:
- echo
- Hello, World!
Much better!
You can also pass data to the sh
function just like the shell
function.
The sh-out
function🔗
The sh-out
function is like the sh
function, but it returns the output as a
string.
$ ys - <<'...'
!YS-v0
say:
sh-out: 'echo "Hello, World!"'
...
Hello, World!
This handy shortcut is often just what the doctor ordered.
The bash
function🔗
You can only run simple shell commands with the shell
and sh
functions.
In other words, you can't do things like pipes and redirects.
Of course you can also put any complicated shell command inside:
bash -c 'complicated | shell > command'
The bash
function basically does this for you in YS code.
$ ys - <<'...'
!YS-v0
say:
get _ :out:
bash: 'fortune | tr a-z A-Z > /tmp/fortune.txt &&
ls -l /tmp/fortune.txt && cat /tmp/fortune.txt'
...
-rw-r--r-- 1 ingy ingy 46 Jul 21 21:27 /tmp/fortune.txt
LOOK AFAR AND SEE THE END FROM THE BEGINNING.
The Shell's the Limit🔗
As you can imagine, there's no limit to what you can do with shell commands in YAML using YS.
Don't worry. Later we'll explore ways to actually limit capabilities in YS if you need to.