Backticks 2.0
When you’ve been bitten by spaces and other odd characters in filenames as
often as I have, you begin to get not a little bit paranoid. Beginners often
make this mistake (ruby syntax, but the same thing happens in bash, perl,
python, etc.):
foo = `file #{filename}`
They quickly learn to do this instead:
foo = `file "#{filename}"`
This works fine until they come across a filename with quotes or any other
characters that are special to the shell from within quotes.
What’s needed is something akin to what can be done with exec and system.
With those two, you can do something like this and it doesn’t matter what
crazy filename is thrown at it, you won’t have any trouble:
system 'file', filename
But exec and system don’t return stdout, like backticks do. The former
doesn’t return at all, and the latter returns the return value. Here is an
idiom that works like glorified array-parameter backticks in ruby:
def backtick(cmd,*args)
IO.popen('-') {|f| f ? f.read : exec(cmd,*args)}
end
Everything you need to understand that code can be found in ri IO.popen and
ri Kernel.exec. If you can think of a better name than backtick do let me
know. Now our code becomes paranoid-friendly:
foo = backtick('file',filename)
While we’re on the subject, a very handy method is Open3#popen3, which is a
bit overkill for this glorified backticks problem but could very well simplify
your life (or mine) in the future.
April 14th, 2008 at 11:12
If you need backticks 1.0 and you hate backticks because they illegible, use %x{echo hello world} instead.
January 21st, 2009 at 06:17
Thanks for that
March 24th, 2009 at 23:17
I like to take that backticks method as defined above and take it a step further like so:
class Symbol
def [] *args
backtick self.to_s, *args
end
end
Then I get to cool stuff like:
:file["-ib", filename]
(: