Runtime Error using Ruby FileUtils - ruby

I've been staring at this for hours, but am not sure what i'm doing wrong. I'm trying to write a simple script to move 100 or so files from various locations in an external list. Should be simple enough, and when I run the command through irb, everything works for that one file, but when running the script I get an error. Here's my script.
#! /opt/local/bin/ruby
require 'fileutils.rb'
list_of_files = File.read "files_to_copy.txt"
source_dir = "/Volumes/data/moved_from_share/"
dest_dir = "/Volumes/data/testeroooo/"
list_of_files.each do |line|
copy_from = source_dir + line
copy_to = dest_dir + line
puts copy_from
puts copy_to
puts
FileUtils.cp_r(copy_from, copy_to)
end
Here is some example input from "files_to_copy.txt":
Accounting HG/Accounts Payable/2011/2011_06/ebi_Inv_218876.pdf
Accounting HG/Accounts Payable/2011/2011_06/expeditors_1050006142.tif
Accounting HG/Accounts Payable/2011/2011_06/expeditors_7050627938.tif
And lastly, here is my output with error:
/Volumes/data/moved_from_share/Accounting PG/Accounts Payable/2011/2011_07/
/Volumes/data/testeroooo/Accounting PG/Accounts Payable/2011/2011_07/
/System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1255:in `copy': unknown file type: /Volumes/data/moved_from_share/Accounting PG/Accounts Payable/2011/2011_07/ (RuntimeError)
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:451:in `copy_entry'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1324:in `traverse'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:448:in `copy_entry'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:423:in `cp_r'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1395:in `fu_each_src_dest'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1411:in `fu_each_src_dest0'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:1393:in `fu_each_src_dest'
from /System/Library/Frameworks/Ruby.framework/Versions/1.8/usr/lib/ruby/1.8/fileutils.rb:422:in `cp_r'
from copy_it.rb:14
from copy_it.rb:8:in `each'
from copy_it.rb:8
If you have any suggestions, I would love to hear them! Thank you!

Your file list likely contains Accounting PG/Accounts Payable/2011/2011_07/ as an entry, which is a Directory, not a File. This should work perfectly fine, as you're using cp_r.
You could override it to only copy files (assuming your file list includes the subfolder items too):
if File.file?(copy_from)
FileUtils.cp_r(copy_from, copy_to)
end

Related

No such file or directory # rb_sysopen ruby

Facing below issue eventhough the file is present in the folder.
H:\Ruby_test_works>ruby hurrah.rb
hurrah.rb:7:in `read': No such file or directory # rb_sysopen - H:/Ruby_
test_works/SVNFolders.txt (Errno::ENOENT)
from hurrah.rb:7:in `block in <main>'
from hurrah.rb:4:in `each_line'
from hurrah.rb:4:in `<main>'
Input file (input.txt) Columns are tab separated.
10.3.2.021.asd 10.3.2.041.def SVNFolders.txt
SubversionNotify Subversionweelta post-commit.bat
Commit message still rake customemail.txt
mckechney.com yahoo.in ReadMe.txt
Code :
dir = 'H:/Ruby_test_works'
file = File.open("#{dir}/input.txt", "r")
file.each_line do |line|
initial, final, file_name = line.split("\t")
#puts file_name
old_value = File.read("#{dir}/#{file_name}")
replace = old_value.gsub( /#{Regexp.escape(initial)}, #{Regexp.escape(final)}/)
File.open("#{dir}/#{file_name}", "w") { |fi| fi.puts replace }
end
I have tried using both forward and backward slashes but no luck. What I'm missing, not sure. Thanks.
puts file_name gives the below values
SVNFolders.txt
post-commit.bat
customemail.txt
ReadMe.txt
The file_name contains the newline character \n at the end, which won't get printed but messes up the path. You can fix the issue by stripping the line first:
initial, final, file_name = line.strip.split("\t")
When debugging code, be careful with puts. Quoting its documentation reveals an ugly truth:
Writes the given object(s) to ios. Writes a newline after any that do not already end with a newline sequence.
Another way to put this is to say it ignores (potential) newlines at the end of the object(s). Which is why you never saw that the file name actually was SVNFolders.txt\n.
Instead of using puts, you can use p when troubleshooting issues. The very short comparison between the two is that puts calls to_s and adds a newline, while p calls inspect on the object. Here is a bit more details about the differences: http://www.garethrees.co.uk/2013/05/04/p-vs-puts-vs-print-in-ruby/
Sometimes the issue is not the file, but the path to the file. Consider compare the file path with what you think the file path is with something like:
File.expand_path('my_file.rb')

Ruby: File not found exception, even though it exists, and is passed down by loop

I'm practicing Ruby after growing to resent Java with a simple little program that determines how similar a few thousand documents are. I did the same thing in Java junior year of high school for a data structures project, and actually wrote the fastest program the teacher had ever seen (apparently), but somehow I can't transfer that over to Ruby.
I'm trying to create an array of files:
array = Dir.foreach("/home/rj/Documents/Ruby Code/Catching Plaigarists/Large number of documents") do |filename|
File.new(filename, "r") unless filename.start_with?(".") #Prevents it from returning current and parent directories
end
When I run it in the terminal, I get this rather irritating exception:
/home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `initialize': No such file or directory # rb_sysopen - bmu390.shtml.txt (Errno::ENOENT)
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `new'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:2:in `block in <main>'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:1:in `foreach'
from /home/rj/Documents/Ruby Code/Catching Plaigarists/y_don_it_work.rb:1:in `<main>'
I checked to make sure the document existed. It did. Ran it again a few more times. Same thing with the same document. Naturally, I tried deleting the document. But then it did the same thing for some other document. And when I deleted that document, it managed to find some problem with some other document with a higher alphabetical precedence that it seemed to do just fine with the first two times around.
Why can't it find these documents, and if they don't exist, why does the loop pass the filenames down in the first place? What am I doing wrong? Why me?
(Also I'm running Fedora with Cinnamon, if that would have any impact.)
Your working directory is different than the directory your looping through. You could store the path your working with as a string and then concatenate it to the filename you get back from your loop.
path = "/home/rj/Documents/Ruby Code/Catching Plaigarists/Large number of documents/"
array = Dir.foreach(path) do |filename|
File.new((path + filename), "r") unless filename.start_with?(".")
end
You'll need the slash at the end of the path variable to build the correct path.

How can I copy files and rename them according to their origin directories using Ruby?

I have many directories with generically named txt files inside. I want to make copies of the txt files, rename them according to the containing directory of each, then move them to the parent directory (that being the directory that holds the directories that hold the original txt files, designated "txts" in the script below). I want to retain the original txt files with their original names in their original directories as well so that nothing within the original directories changes.
I have an old script that I think achieved (some of) my goals once, perhaps moving instead of copying the original txt files, but I'm unable to run it successfully now:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
ret = path.scan(/.*txts\/([^\/]+)\/.*/)
name = ret[0].to_s + ".txt"
FileUtils.mv(path, name)
end
Years ago a friend wrote this and ran it from within a unix environment with success. When I run it now, an enormous number of errors are returned. I'm using Ruby 2.2.2 and it's entirely possible there's a placeholder somewhere that I'm too newbish to recognize, or perhaps something changed from the older version of FileUtils... I truly have no idea and am afraid I've been unable to turn up any answers with my neophyte skills.
And so I appeal to you...
Edit: Here's the error message:
C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `stat': Invalid argument # rb_file
_s_stat - ["may2013"].txt (Errno::EINVAL)
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1328:in `lstat'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1247:in `exist?'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:519:in `block in mv'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1570:in `block in fu_each_src
_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1586:in `fu_each_src_dest0'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:1568:in `fu_each_src_dest'
from C:/Ruby22/lib/ruby/2.2.0/fileutils.rb:516:in `mv'
from extracttxt.rb:12:in `block in <main>'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:48:in `block (2 levels) in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `catch'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:47:in `block in find'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `each'
from C:/Ruby22/lib/ruby/2.2.0/find.rb:42:in `find'
from extracttxt.rb:6:in `<main>'
The error message shows that ret[0] is the array [ "may13" ], so ret[0].to_s + ".txt" evaluates to the string ["may13"].txt. I'm not sure, but it's possible the behavior of String#scan changed in Ruby 1.9 or 2.0, so it returns an array of arrays when captures are present, whereas before it returned an array of strings.
Something like this ought to solve the problem:
require 'find'
require 'fileutils'
Find.find("txts") do |path|
if FileTest.directory?(path)
next
end
if path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
end
If you want to match by file extension you could either add it to the Regexp above (e.g. %r{txts/([^/]+)/.+\.txt$}) or you could use Dir[] (a.k.a. Dir.glob) e.g.:
require 'dir'
require 'fileutils'
Dir['txts/**/*.txt'].each do |path|
next if FileTest.directory?(path) ||
next unless path =~ %r{txts/([^/]+)/}
FileUtils.cp(path, "#{$1}.txt")
end
I don't know if there will be any performance difference, but it might be worth trying.

Search and Replace within one file

i'm new to Ruby and i'm trying to use RegEx to do multiple search and replaces in an input text file, however my code isn't working, i think i understand why it doesn't work but i don't know the syntax i need to make it work.
Heres my code:
# encoding: utf-8
#!/usr/bin/ruby
# open file to read and write
file = File.open("input.txt", "r+")
# get the contents of the file
contents = file.read
file.close
reassign = contents.gsub(/\w+/, '£££££')
# save it out as a new file
new_file = File.new("output.txt")
new_file.write(reassign)
new_file.close
this is the error messages:
C:/Users/parsonsr/RubymineProjects/Test 3/test3.rb:14:in `write': not opened for writing (IOError)
from C:/Users/parsonsr/RubymineProjects/Test 3/test3.rb:14:in `<top (required)>'
from -e:1:in `load'
from -e:1:in `<main>'
i tried using an array to pass each line through and change whats relevant but then it only saves whats in the array to the output not the rest of the file.
I either need it to change the text thats already there within one file or change the text then save the file with the new changes made into an output file, whichever is easiest.
Hope this makes sense.
Thanks
Take a look at the documentation. Note that File#open receives mode "r" by default.
So the answer is: change
File.new("output.txt")
to
File.new("output.txt", "w")
Another thing you can do in Ruby is:
File.write("output.txt", reassign)
Or:
File.open("output.txt", "w")
Also, i don't know what's the purpose, but consider a big file, you might want to read batch of lines and write them to the output file each time, not read all at once to the memory.

Reading Files in Ruby

So, I'm relatively new to programming, and I have started working with ruby. I am going through "Learn how to code the hard way: Ruby" and I am on exercise 15; the beginning of file reading. I have copied the code they provided word for word, literally copy and pasted it to make sure, but I am getting the same error. I've googled the error, but to no avail. I have the .rb file in the same directory as the .txt file I'm trying to read. Here is my code.
filename = ARGV.first
prompt = "> "
txt = File.open(filename)
puts "Here's your file: #{filename}"
puts txt.read()
puts "I'll also ask you to type it again:"
print prompt
file_again = STDIN.gets.chomp()
txt_again = File.open(file_again)
puts txt_again.read()
The error I keep getting it this:
ex15.rb:19:in 'initialize': No such file of directory - ex15.txt <Errno::ENOENT>
from ex15.rb:4:in 'open'
from ex15.rb:4:in '<main>'
command to run it:
ruby ex15.rb ex15.txt
Any help is appreciated. Thanks
When you don't specify the mode argument for File.open(), the default is 'r', which stands for read. And to read a file, it has to exist already. The error message is telling you that there is no file named 'ex15.txt' in the current directory for ruby to read.
To get rid of the error, create a file called ex15.txt in the current directory, and type 'hello world' in the file.

Resources