How to provide quoted parameters to System.cmd

Hello everyone,

I am trying to run image magick convert from Elixir. The command I am trying to replicate is…

$ convert -size 200x200 xc:Black -fill White -draw 'circle 100 100 100 1' -alpha Copy mask.png

Which is working fine in the shell. It generates a new image correctly.

And now I am trying to do this in the BEAM.

  def build_mask(size) do
    params = [
      "-size",
      "#{size}x#{size}",
      "xc:Black",
      "-fill",
      "White",
      "-draw",
      "'circle 100 100 100 1'",
      "-alpha",
      "Copy",
      "mask.png"
    ]
    System.cmd(convert(), params)
  end

  defp convert() do
    case System.cmd("which", ["convert"]) do
      {convert_cmd, 0} -> String.trim_trailing(convert_cmd, "\n")
      {_, 1} -> ""
    end
  end

which fails with

convert: non-conforming drawing primitive definition `circle 100 100 100 1' @ error/draw.c/RenderMVGContent/4397.

The problem is in these lines, if I comment them, the command is working.

"-draw",
"'circle 100 100 100 1'",

So my question is how to pass a quoted parameters like this ‘circle 100 100 100 1’.

I have been trying different combination, with escape, double quote and what not.

Does anybody hit the same problem trying to wrap convert command in the BEAM?

Thanks for taking time

The quotes are a shell thing, just leave them off and just use "circle 100 100 100 1".

6 Likes

Oh my… it is now working fine :slight_smile:

2 Likes

I’m running into a similar issue trying to run wkhtmltopdf with a string HTML.

    html_string =
      Phoenix.View.render_to_string(FooWeb.PdfView, "contract.html",
        test_name: "Brawl Smash Bros."
      )

    download_folder = Application.app_dir(:myapp, ["priv", "static", "pdfs"])
    pdf_save_path = "#{download_folder}/contract.pdf"

    IO.inspect("wkhtmltopdf " <> html_string <> " " <> pdf_save_path)

    System.cmd("wkhtmltopdf", [html_string, pdf_save_path])

Result:

iex [16] > myapp.Pdf.generate_team_contract()
"wkhtmltopdf <h1>This is your team contract</h1>\n\n<p>You are playing in Brawl Smash Bros.</p> /home/sergio/Work/myapp/_build/dev/lib/myapp/priv/static/pdfs/team-contract.pdf"
Loading pages (1/6)
Error: Failed to load http:/p>, with network status code 3 and http status code 0 - Host  not found
                                                                                                   Error: Failed loading page http:/h1>

                  <p>You are playing in Brawl Smash Bros.</p> (sometimes it will work just to ignore this error with --load-error-handling ignore)
                             Exit with code 1 due to network error: HostNotFoundError
                                                                                     {"", 1}

Anyone have any tips on how to run this command? The HTML isn’t being quoted.

I don’t see any mention of passing HTML directly via the command line in the wkhtmltopdf docs, escaped or otherwise.

wkhtmltopdf expects a URL or file. You’ll have to File.write(tmp_html_path, html_string) and System.cmd("wkhtmltopdf", [tmp_html_path, pdf_save_path])

Maybe I misread? I thought you could pass in a string.

That answer is about piping the output of echo in bash, I don’t think you can do that within Elixir.

I was going by the help file linked above by @al2o3cr

A page objects puts the content of a single webpage into the output document.
(page)? <input url/file name> [PAGE OPTION]…