Is there any way to run an external command with * in it?


I am trying to run an external command "rsync * a: " with run() and the * makes it impossible. there is an old unresolved question on this. How to quote special characters in run() function

I am now making a detour to R to make it happen
system(“rsync * a:”)
but that seems very inelegant.

Is there a way to do this natively in Julia?

best regards, Jack

You can use the Glob.jl package:

run(`rsync $(glob("*")) a:`)

Thanks fredrikekre!

That worked brilliantly! And I would never have thought of that usage of glob.

best, Jack

The problem is not quoting or “special characters”. You can do run(`rsync "*" a:"`) which passes the * to rsync just fine. However, it looks like you don’t actually want to pass * to rsync — you want * expansion (globbing), but this is performed by the shell and Julia’s run does not invoke the shell — it runs rsync directly.

If you want to run rsync via a shell, you can do so by directly invoking sh -c, i.e.:

run(`sh -c "rsync * a:"`)

(Invoking a shell is what R’s system function is doing.)

However, invoking the shell is a suboptimal approach in general. Not only is it slower (first the system launches a sh process, then sh launches rsync), but it also runs into lots of brittle issues with quoting. (And there are portability problems, e.g. on Windows.)

That’s why we generally recommend pure-Julia alternatives to shell features, like the Glob.jl package if you want to do glob expansion of paths, or Julia’s pipeline function if you want to pipe.


Thanks stevengj

That makes perfect sense to me. I am indeed globbing and it works as it should with Glob.jl.

all the best, Jack

1 Like