Skip to content

Commit 88a8a6a

Browse files
committed
blog: Add 2025-07-21.md
1 parent 1e5705b commit 88a8a6a

1 file changed

Lines changed: 158 additions & 0 deletions

File tree

blog/2025-07-21.md

Lines changed: 158 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,158 @@
1+
---
2+
title: Calling Shell Commands from YAML
3+
date: 2025-07-21
4+
draft: false
5+
authors: [ingydotnet]
6+
categories: [Summer-of-YS]
7+
edit: blog/2025-07-21.md
8+
comments: true
9+
---
10+
11+
Wouldn't it be handy to get data from shell commands in YAML?
12+
13+
Well you can, and it's really easy.
14+
15+
YS has a bunch of functions in its Standard Library for calling shell commands,
16+
and passing data to and from them.
17+
18+
Let's take a look...
19+
20+
<!-- more -->
21+
22+
23+
## The `shell` function
24+
25+
When you just want to run a shell command and let its outputs print to the
26+
terminal, you can use the `shell` function.
27+
28+
```bash
29+
$ ys - <<'...'
30+
!YS-v0
31+
shell: 'fortune'
32+
...
33+
You have taken yourself too seriously.
34+
```
35+
36+
This is the same as running `fortune` in from the command line.
37+
38+
You can also pass data to the shell command.
39+
Let's try the `tac` command, which reverses the lines of a file.
40+
41+
```bash
42+
$ ys - <<'...'
43+
!YS-v0
44+
shell {:in "foo\nbar\nbaz\n"}: 'tac'
45+
...
46+
baz
47+
bar
48+
foo
49+
```
50+
51+
52+
## The `sh` function
53+
54+
The `sh` function doesn't print the output to the terminal.
55+
It returns a mapping that contains a bunch of fields like the exit code, stdout,
56+
stderr, and more.
57+
58+
```bash
59+
$ ys - <<'...'
60+
!YS-v0
61+
result =:
62+
sh: 'echo "Hello, World!"'
63+
say: result.out
64+
...
65+
Hello, World!
66+
```
67+
68+
Let's look at the entire result object:
69+
70+
```bash
71+
$ ys - <<'...'
72+
!YS-v0
73+
result =:
74+
sh: 'echo "Hello, World!"'
75+
say: result
76+
...
77+
{: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!
78+
, :err , :prev nil, :cmd [echo Hello, World!]}
79+
```
80+
81+
That's kind of ugly and hard to read.
82+
83+
Let's use the `yaml/dump` function to pretty print it:
84+
85+
```bash
86+
$ ys - <<'...'
87+
!YS-v0
88+
result =:
89+
sh: 'echo "Hello, World!"'
90+
say: result:yaml/dump
91+
...
92+
proc: !!java.lang.ProcessImpl {}
93+
exit: 0
94+
in: !!java.lang.ProcessImpl$ProcessPipeOutputStream {}
95+
out: |
96+
Hello, World!
97+
err: ''
98+
prev: null
99+
cmd:
100+
- echo
101+
- Hello, World!
102+
```
103+
104+
Much better!
105+
106+
You can also pass data to the `sh` function just like the `shell` function.
107+
108+
109+
## The `sh-out` function
110+
111+
The `sh-out` function is like the `sh` function, but it returns the output as a
112+
string.
113+
114+
```bash
115+
$ ys - <<'...'
116+
!YS-v0
117+
say:
118+
sh-out: 'echo "Hello, World!"'
119+
...
120+
Hello, World!
121+
```
122+
123+
This handy shortcut is often just what the doctor ordered.
124+
125+
126+
## The `bash` function
127+
128+
You can only run simple shell commands with the `shell` and `sh` functions.
129+
130+
In other words, you can't do things like pipes and redirects.
131+
132+
Of course you can also put any complicated shell command inside:
133+
134+
```
135+
bash -c 'complicated | shell > command'
136+
```
137+
138+
The `bash` function basically does this for you in YS code.
139+
140+
```bash
141+
$ ys - <<'...'
142+
!YS-v0
143+
say:
144+
get _ :out:
145+
bash: 'fortune | tr a-z A-Z > /tmp/fortune.txt &&
146+
ls -l /tmp/fortune.txt && cat /tmp/fortune.txt'
147+
...
148+
-rw-r--r-- 1 ingy ingy 46 Jul 21 21:27 /tmp/fortune.txt
149+
LOOK AFAR AND SEE THE END FROM THE BEGINNING.
150+
```
151+
152+
## The Shell's the Limit
153+
154+
As you can imagine, there's no limit to what you can do with shell commands in
155+
YAML using YS.
156+
157+
Don't worry.
158+
Later we'll explore ways to actually limit capabilities in YS if you need to.

0 commit comments

Comments
 (0)