Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Executing a basic shell command in Elixir

Tags:

erlang

elixir

At a very early stage of learning the language, and working through the ElixirSips series of videos. I keep hitting stuff that's been slightly obseleted by language changes. Trying to wrap my head around this, and Google/Github issue trackers/SO trawling is getting me nowhere useful. I have this very basic module, which should just run a shell command:

defmodule QuickieSynth.Sound do
  def command(note) do
    "play -qn synth 2 pluck #{note}"
  end

  def play(note) do
    note |> command |> System.cmd
  end
end

However, when this file is compiled and the tests run, I get an argument error; fair enough - System.cmd/1 seems to no longer be part of the standard lib.

System.cmd/3 is in the standard lib, and reading the docs indicated the options are, well, optional. So I pass empty args note |> command |> System.cmd([]), and what I get back is erlang: :enoent: again after reading the docs a bit more carefully, fair enough.

So I try to use Erlang's :os.cmd/1, so note |> command |> :os.cmd, and I get (FunctionClauseError) no function clause matching in :os.validate/1. And I am now stuck.

like image 863
DanCouper Avatar asked Dec 29 '14 12:12

DanCouper


People also ask

How do shell commands work?

The shell parses the command line and finds the program to execute. It passes any options and arguments to the program as part of a new process for the command such as ps above. While the process is running ps above the shell waits for the process to complete.

What are shell commands?

A shell is a computer program that presents a command line interface which allows you to control your computer using commands entered with a keyboard instead of controlling graphical user interfaces (GUIs) with a mouse/keyboard/touchscreen combination.

How do I run a shell script in R studio?

In RStudio, commands can be executed from shell scripts by pressing Ctrl + Enter .


1 Answers

System.cmd/3 seems to accept the arguments to the command as a list and is not happy when you try to sneak in arguments in the command name. For example System.cmd("ls", ["-al"]) works, while System.cmd("ls -al", []) does not. So in your case you'll probably need something like:

System.cmd("play", ["-qn", "synth", "2", "pluck", note])

What in fact happens underneath is System.cmd/3 calls :os.find_executable/1 with its first argument, which works just fine for something like ls but returns false for ls -al.

If you decide to go the pure erlang route, then the call expects a char list instead of a binary, so you need something like the following:

"ls -al" |> String.to_char_list |> :os.cmd
like image 79
Paweł Obrok Avatar answered Sep 27 '22 19:09

Paweł Obrok