Create a Cmd from a String

question

#1

I am using Julia to combine information from a combination of sources and generate a (rather lengthy) string that is a call to an external program. I can generate a String containing the text that I would type into the shell but I can’t work out how to turn that into a Cmd to call with run. I currently get around that by writing the string to a file named cmd.sh and calling

run(`/bin/bash cmd.sh`)

but I am convinced there has to be a better way.

I tried

run(Cmd([mystring;]))

but that seemed to generate extra quotes.

Can someone suggest how I can do this?


#2

If you need to run it in the shell then run(`sh -c $cmd`) is best (where cmd is a String variable)

If you just need to pass multiple arguments, then call just run(cmd), where cmd is built up from interpolating other Cmd objects and arrays of Strings.


#3

Unfortunately the first version doesn’t work because the contents of $cmd are enclosed in double quotes. To the shell, it looks like one long file name.

I want to run

myprog --a=optiona --b=="option b" file1 file2

not

"myprog --a=optiona --b==\"option b\" file1 file2"

It seems that I will need to stay with the current approach or try to use your second approach and right now I think writing to a file then executing that as a shell script is easier.

I appreciate that appropriately quoting strings that are parts of commands is important but not having a way to override the quoting is awkward.


#4

The right way to do this is to avoid the shell completely. e.g. suppose you have an array filenames of filenames strings and an array options with the option strings. You would construct the command to run by, for example:

options = ["--a=optiona", "--b=option b"]
filenames = ["file1", "file2"]
`myprog $options $filenames`

Note that in the options variable, there is no need for additional quoting. You write "--b=option b", not "--b=\"option b\"". The reason is that these options are passed directly to myprog, without going through the shell.

Avoiding the whole issue of quoting and escapes is a huge benefit of circumventing the shell, along with the performance advantage of not launching the shell process.


#5

Thank you, @stevengj. I’ll let that be a lesson to myself to always give an example of what I am trying to accomplish.

It is all working well now.


#6

Also note that writing a command literal (inside backticks) will also work.

Here cmd1 and cmd2 are equivalent:

cmd1 = `myprog --a=optiona --b="option b" file1 file2`
options = ["--a=optiona", "--b=option b"]
filenames = ["file1", "file2"]
cmd2 = `myprog $options $filenames`