System.cmd "cd", path --> returns an error

All 3 commands return an error. How to fix it?

iex(1)> System.cmd "cd /opt/", []
** (ErlangError) erlang error: :enoent
    (elixir) lib/system.ex:564: System.cmd("cd /opt/", [], [])

iex(1)> System.cmd "cd /opt", [] 
** (ErlangError) erlang error: :enoent
    (elixir) lib/system.ex:564: System.cmd("cd /opt", [], [])

iex(1)> System.cmd "cd", ["/opt"]   
** (ErlangError) erlang error: :enoent
    (elixir) lib/system.ex:564: System.cmd("cd", ["/opt"], [])

cd is a built in, not an actual program, you can’t shell out to it. Even if you could, the change of working directory were only happening in the subshell, and lost with it, when cmd/2 returns.

You have to use File.cd/1 or File.cd!/1 instead.

3 Likes

Also this works well from the terminal:

      $tar -czf sometthing.tar.gz *.txt

But the same thing from Elixir not – it creates an empty archieve:

      System.cmd("tar", ["czf", "sometthing.tar.gz", "*.txt"])

And this again also works well:

      System.cmd("tar", ["czf", "sometthing.tar.gz", "file1.txt", "file2.txt"])

How to fix that?

1 Like

@kaa.python the expansion of wildcards is also done by the shell, and not the tar program. You need to call Path.wildcard in Elixir if you want to expand wildcards for a certain path. For example:

System.cmd "tar", ["czf", "something.tar.gz" | Path.wildcard("*.txt")]
5 Likes

Alternatively, it’s possible to call the shell and let it do the expansion. This is also what you’d use to take advantage of other shell features like | pipes or > redirection.

System.cmd "sh" ["-c", "tar czf something.tar.gz *.txt"]
4 Likes

that doesn’t work for the case when I’ll also need “cd /home/user123/some_folder”, does it?

System.cmd "sh" ["-c", "cd /home/user123/some_folder; tar czf something.tar.gz *.txt"]

That should work. I do similar stuff all the time in my daily to use helper scripts (the are zsh scripts shelling into bash for reasons…)