From: Bill Kelly Date: 2009-11-11T08:43:05+09:00 Subject: Re: Calling a subprocess with specific arguments and capturing its output? From: "Dan Q" > > Hi. I haven't written Ruby in a while, and I was wondering if someone > could help with a problem I've never managed to solve. I'm writing a > shell script that takes filenames as its arguments, and calls "du" to > get their size. Because I don't want to have to escape everything > perfectly, I was looking for a function with a syntax that allows > separate arguments, like system("du", "-sh", filename). > > system() doesn't allow me to capture the output of the subprocess, > while popen , ``, and %x() don't let me specify a list of discrete > arguments. Is there an elegant solution to this problem? My current > solution is to just escape the arguments and put them into a string, > but this is ugly and buggy. One possibility might be to let Shellwords handle the escaping: irb(main):001:0> require 'shellwords' irb(main):002:0> args = ["foo", "bar baz", "mary 'had' a", 'little "lamb" and stuff'] irb(main):003:0> puts( args.map {|a| a.shellescape}.join(" ") ) foo bar\ baz mary\ \'had\'\ a little\ \"lamb\"\ and\ stuff Alternately, if you can use ruby 1.9.x, there appears to be a very powerful new Kernel.spawn command. (See the `ri` documentation, several pages...) Also in 1.9.x, it appears to now be possible to pass an Array for the command arguments to popen: irb(main):001:0> IO.popen(["ls", "-l", "GL_GameOfLife.zip", "quake3-1.32b-source.zip"], "r") {|io| puts(io.read)} -rw------- 1 billk billk 3540592 Feb 23 2009 GL_GameOfLife.zip -rw------- 1 billk billk 5724791 Sep 21 2005 quake3-1.32b-source.zip Hope this helps, Bill