0

I have code that invokes two system commands that write to a file and I need to add something else from my code in between these calls:

File.open('test.txt', 'w') {|f|
  `echo 1 > #{f.path}`
  f.write '2'
  `echo 3 >> #{f.path}`
}

as the result the file contains just

2
3

the first line is missing. I am sure there is a simple solution, but I cannot find it.

akonsu
  • 28,824
  • 33
  • 119
  • 194

2 Answers2

1

You are opening the file in "write" mode which is clobbering the first echo. Instead use 'append' mode. Additionally, you're not flushing after you write "2" so it'll be out of order when you read it back. Remember, f.write doesn't append a newline, so you probably need that too.

irb(main):020:0> File.open('asdf', 'a') do |f|
irb(main):021:1*   `echo 1 > asdf`
irb(main):022:1>   f.write("2\n") and f.flush
irb(main):023:1>   `echo 3 >> asdf`
irb(main):024:1> end
=> ""
irb(main):025:0> File.read('asdf')
=> "1\n2\n3\n"
irb(main):026:0> puts File.read('asdf')
1
2
3

The File.open(name, 'a') is the important part. It means append to this file instead of overwriting it. See http://www.ruby-doc.org/core-2.0/IO.html#method-c-new and What are the Ruby File.open modes and options? for descriptions of file open modes.

If it's important to delete any existing file, the first echo will implicitly take care of that (since it's a single >). Or you can do it in ruby explicitly:

File.delete('asdf') if File.exists?('asdf')
Community
  • 1
  • 1
olamork
  • 179
  • 4
  • thanks. I do not understand why opening the file in `'w'` mode clobbers the first `echo`. In addition, I need to destroy any existing file before writing to it. – akonsu Jul 26 '13 at 16:38
  • I don't know exactly how the File internals work. It's likely that it doesn't actually persist anything to disk until the block exits or flush is called. When this happens it'll overwrite the echo. – olamork Jul 26 '13 at 16:45
0

to answer my own question:

File.open('test.txt', 'w') {|f|
  `echo 11 > #{f.path}`
  f.seek(0, IO::SEEK_END)
  f.write "2\n"
  f.flush
  `echo 33 >> #{f.path}`
}
akonsu
  • 28,824
  • 33
  • 119
  • 194