views:

614

answers:

1

As an example i want to run the following command under a rake.

robocopy C:\Media \\other\Media /mir

The rakefile i was able to get working was

def sh(str)
  str.tr!('|', '\\')
  IO.popen(str) do |pipe|
    pipe.each do |line|
      puts line
    end
  end
end

task :default do
  sh 'robocopy C:|Media ||other|Media /mir'
end

However the handling of the string literal is awkward.

If i use a heredoc to enter the string literal

<<HEREDOC
copy C:\Media \\other\Media /mir
HEREDOC

i get the error

rakefile.rb:15: Invalid escape character syntax
copy C:\Media \\other\Media /mir
          ^
rakefile.rb:15: Invalid escape character syntax
copy C:\Media \\other\Media /mir
                        ^

if i use single quotes, one of the back slashes gets lost.

irb(main):001:0> 'copy C:\Media \\other\Media /mir'
=> "copy C:\\Media \\other\\Media /mir"
+2  A: 

Double backslash is interpreted as an escaped single backslash. You should escape each backslash in the string.

irb(main):001:0> puts 'robocopy C:\\Media \\\\other\\Media /mir'
robocopy C:\Media \\other\Media /mir

Or, if you really don't want to escape the backslashes, you can use a here doc with a single quoted identifier.

irb(main):001:0> <<'HEREDOC'
irb(main):002:0' copy C:\Media \\other\Media /mir
irb(main):003:0' HEREDOC
=> "copy C:\\Media \\\\other\\Media /mir\n"
irb(main):004:0> puts _
copy C:\Media \\other\Media /mir
Jeff Dallien
yes, but like the code i listed in the question it is awkward escaping all the backslash characters.
Frank
I think simply escaping the backslashes in a string is the least awkward of all, but I updated the answer with a workable here doc syntax.
Jeff Dallien
okay, great! HEREDOC's are the way to go... that's the first time ive seen the <<'HEREDOC' syntax. Why did not my <<HEREDOC do exactly the same thing?
Frank
The type of quotes indicate how to process the string. Also valid are backticks (`) to execute shell commands. See http://www.ruby-doc.org/docs/ruby-doc-bundle/Manual/man-1.4/syntax.html#here_doc
Jeff Dallien