Error when using System.cmd

Hi there, I’m having some trouble with the “System” module, specifically the cmd function. My code is the following, which is exactly the same as the documentation, StackOverflow/Elixir forum answers, etc:

System.cmd("echo", ["Hello"])

I’m getting the following error:

** (ErlangError) Erlang error: :enoent
    (elixir 1.10.4) lib/system.ex:795: System.cmd("echo", ["Hello"], [])
    (elixir 1.10.4) lib/code.ex:926: Code.require_file/2

I understand the “enoent” means “No such file or directory”, however, I don’t understand what file or directory could possibly be required in this case. It’s probably an elementary mistake which wouldn’t surprise me as I’m new to Elixir/Erlang. There are 2 things worth mentioning, in my opinion. The first is that surrounding the words “echo” and “Hello” in single quotes instead of double quotes, so System.cmd(‘echo’, [‘Hello’]), produces a different error:

** (FunctionClauseError) no function clause matching in System.cmd/3

    The following arguments were given to System.cmd/3:

        # 1
        'echo'

        # 2
        ['Hello']

        # 3
        []

    Attempted function clauses (showing 1 out of 1):

        def cmd(+command+, +args+, +opts+) when -is_binary(command)- and +is_list(args)+

    (elixir 1.10.4) lib/system.ex:782: System.cmd/3
    (elixir 1.10.4) lib/code.ex:926: Code.require_file/2

probably unrelated although I’m guessing this means that double quotes and single quotes are different in elixir. The other thing is that the following command works:

IO.puts "echo Hello" |> String.to_charlist |> :os.cmd

Although this one seems to return the result of running the command instead of directly running it in the running shell, hence the IO.puts, and I assume this isn’t the same behaviour as System.cmd
My apologies for the long post, but hopefully we can clear some things up here, and thanks in advance

The function requires a binary (string with double quotes) and not a charlist (string with single quotes). That’s is the argument error that you’re getting. :os.cmd is the Erlang equivalent function.

Are you using Windows or a Unix-like OS?

:os.cmd use a shell while System.Cmd doesn’t. In a Unix like os, echo is both a shell builtin and an external command as /bin/echo so both should work. Like the other replier guessed you probrably don’t have /bin/echo

I’m using Windows, probably shouldv’e mentioned it. However, echo does work in windows, no? I also tried dir just in case, and it didn’t work either

In windows echo as well as dir are strict built-in a, there is no way to call them as binary.

You probably need to do something like System.cmd("cmd", ["-c", "echo foo"]) or something like that.

Could you point me to the relevant resources or search terms? At this point I’m not sure what to look for in this case

Back in the days, MS-DOS came with a good help program, very close to man on unix systems, but for actual DOS tools and builtins only.

Not sure if this is still available in todays cmd.exe, but to be honest, I doubt it is… With a bit of luck there is some /help or --help switch for cmd.exe that you can try.

Also, you might try where, to see if a command is available in the PATH. If windows is a nice person, it will tell you that dir is actually a builtin, if its nasty it will just tell you that its not available in PATH.

Also, the information microsoft gives away about what is or is not available in cmd.exe gets more sparse every year, as they try hard to encourage users to do more PowerShell instead.

is it possible to run PowerShell commands from Elixir instead?

Yes, by calling Powershell instead of cmd and passing it the command/script with appropriate command line flags.

1 Like

The first thing I do on Windows is to install msys2 which gives you a sane command line interface.

Cmd is dead. PowerShell is nice however it is not significantly better than bash so I don’t see the point of being different from everybody else.

2 Likes