Run a shell command with a pipe operator

It is strange that :os.cmd accepts an atom for the command name, looks like a historical accident.

In general, functions from the Erlang standard library take character lists where in Elixir you would use a string. To make it more confusing, the Erlang type for such lists is called string(). I recommend taking a look at this cheat sheet if you still feel confused.

Going back to your problem, Ben has already done a good job explaining the difference between Elixir’s System.cmd and Erlang’s :os.cmd. In the source code for :os.cmd you can see it actually spawns a shell appropriate for the current OS and evaluates the string you’ve passed to the function in that shell.

Replicating this behaviour for your particular example using System.cmd is easy:

System.cmd("sh", ["sleep 0.1 | echo foo"])