How to read files from a directory in ruby - ruby

Ruby Beginner.
Learning to write to files, in a directory. Wondering how to now read those files from a directory? Assume there's a directory "book_test" with some .txt files, with a line of text in each file.
puts "Enter name:"
name = gets.strip
filename = "#{name}.txt"
puts "Enter number:"
number = gets.strip
number_in_file = "#{number}"
File.write("/Users/realfauxreal/book_test/#{filename}", number_in_file)
so far so good. I can add a bunch of .txt files with some numbers (or whatever) in them, to the "book_test" dir.
Now If I want to retrieve them, obviously this doesn't work.
Dir.open "/Users/realfauxreal/book_test" do |dir|
dir.each do |name, number|
puts "#{name}, #{number}"
end
end
Am I on the right track? Obviously this isn't outputting properly, plus there are some additional files that I don't want to show up. Is this a case for the .glob helper?
If I'm way off base, any tips would be appreciated.

Using Dir::[], File::basename and File::read
Dir['/Users/realfauxreal/book_test/*.txt'].each do |file_path|
p "#{File.basename(file_path)}, #{File.read(file_path)}"
end
"foo.txt, 2"
=> ["book_test/foo.txt"]

Related

Search for a .yml file in a folder

I have developed a system where a specific user has access to search for a specific file. The problem is that this file is in a folder so I am having a hard time coding it.
My method must be able to find my keyword input in the file name.
For example, If I search for Bob, I will get all the files where Bob are included in the filename
def search_user(search)
keyword = File.readlines('test3.yml')
matches = keyword.select { |username| username[/#{search}/] }
if File.read("test3.yml").include?(search)
puts "_____________________________________________"
puts ("Search results for student: " + search + ":") #
puts
puts matches
puts "_____________________________________________"
else #If not it will give the user feedback that its not there
puts "_____________________________________________"
puts
puts ("Sorry, we couldnt find #{search} in the system.")
puts "_____________________________________________"
end
end

Ruby - Writing filenames from subfolders to a txt file

I have 385 subfolders in a directory, each containing a CSV file along with several pdfs. I'm trying to find a way to go through each subfolder and write a list of the pdfs to a txt file. (I realize there are better languages out there to do this than Ruby, but I'm new to programming and it's the only language I know.)
I have code that gets the job done, but the problem I'm running into is it's listing the subfolder directory as well. Example: Instead of writing "document.pdf" to a text file, it's writing "subfolder/document.pdf."
Can someone please show me how to write just the pdf filename?
Thanks in advance! Here's my code:
class Account
attr_reader :account_name, :account_acronym, :account_series
attr_accessor :account_directory
def initialize
#account_name = account_name
#account_series = account_series
#account_directory = account_directory
end
#prompts user for account name and record series so it can create the directory
def validation_account
print "What account?"
account_name = gets.chomp
print "What Record Series? "
account_series = gets.chomp
account_directory = "c:/Processed Batches Clone/" + account_name + "/" + account_series + "/Data"
puts account_directory
return account_directory
end
end
processed_batches_dir = Account.new
#changes pwd to account directory
Dir.chdir "#{processed_batches_dir.validation_account}"
# pdf list
processed_docs = []
# iterates through subfolders and creates list
Dir.glob("**/*.pdf") { |file|
processed_docs.push(file)
}
# writes list to .txt file
File.open("processed_batches.txt","w") { |file|
file.puts(processed_docs)
}
There may be a better way, but you could always split on the last slash in the path:
Dir.glob('**/*.pdf').each do |file_with_path|
processed_docs.push(file_with_path.split('/').last)
end

How to name just created .TXT files in such a way that file name differs each time

I have compiled the user's answers into a .TXT file and move it to another location, where I would store all the answers. I would need that .TXT to be named differently each time a user runs the application, so that the file is not replaced. I thought about appending time stamps next to the original name, but not sure how to do that.
My code:
require 'FileUtils'
puts "1) How would you rate the manual? Range: 1-10."
rating_range = gets.to_i
puts "2) How could the manual be improved? Type your answer below:"
improvement = gets.chomp
puts "3) What would you add to the manual. Type your answer below:"
addition = gets.chomp
puts "4) Indicate any general comments you would like to add:"
general_comments = gets.chomp
File.open("Survey.txt", 'w') { |file|
file << "1) #{rating_range}\n"
file << "2) #{improvement}\n"
file << "3) #{addition}\n"
file << "4) #{general_comments}\n"
}
FileUtils.mv('/Documents/Survey.txt', '/Stuff')
The file Survey.txt should be named differently each time.
Any ideas?
Time.now
http://ruby-doc.org/core-2.2.0/Time.html
filename = "Survey-#{Time.now}"
File.open(filename, 'w')
FileUtils.mv(filename, '/Stuff')
Timestamps aren't really guaranteed to be unique. Although it's unlikely you'd get exact duplicates, it's still possible. If you're looking for a file solution, you can use a UUID:
require 'securerandom'
uuid = SecureRandom.uuid
File.open("Survey-#{uuid}.txt", 'w') { |file|
...
}
Of course for a more robust solution, you should be using a database. :)
Try replacing
File.open("Survey.txt", 'w') { |file|
with
File.open("Survey_" + Time.now.to_i.to_s + ".txt", 'w') { |file|
This will append the time in seconds since the unix epoch to the filename. If you just use Time.now you'll end up with characters like colons in the filename, which could be problematic depending on your filesystem.
Do you just want to differentiate files, or does the timestamp need to be readable?

Delete a line of information from a text file

I have a text file called text.txt, and it has the following text:
123,shirt,9.99
234,pants,19.50
456,socks,3.99
How do I delete one row (e.g 123,shirt,9.99). How would I go about deleting this row?
My code so far:
test_file = File.new('text.txt', "a")
while (line = test_file)
puts 'Enter the products item number you wish to delete. '
user_delete = gets.chomp.to_i
line.delete(user_delete)
end
You're making a lot of mistakes here.
First of all opening the file with a (you need to use r+ or w+).
In Ruby we use a more elegant to iterate over files.
Check this answer, it will help you with your problem.
After that a look at IO library to understand how it all works
I imagine there are a bunch of better ways to do this, but here's quick and dirty:
puts "What's the item number?"
item_num = gets.chomp
read_file = File.new('read.txt', "r").read
write_file = File.new('read.txt', "w")
read_file.each_line do |line|
write_file.write(line) unless line.include? item_num
end

Trying to change names of files using Dir and File.rename on Mac OS?

I'm following a tutorial and am trying to change the names of three files in a folder that's located under 'drive/users/myname/test'. I'm getting the error:
'chdir': No such file or directory - test'.
The starting path is already 'drive/users/myname', which is why I thought that I only had to enter 'test' for Dir.chdir.
How do I correctly input the paths on Mac OS?
Dir.chdir('test')
pic_names = Dir['test.{JPG,jpg}']
puts "What do you want to call this batch"
batch_name = gets.chomp
puts
print "Downloading #{pic_names.length} files: "
pic_number = 1
pic_names.each do |p|
print '.'
new_name = "batch_name#{pic_number}.jpg"
File.rename(name, new_name)
pic_number += 1
end
I think you have to provide the absolute path. So, your first line should be:
Dir.chdir("/drive/users/myname/test")
According to the documentation:
Dir.chdir("/var/spool/mail")
puts Dir.pwd
should output/var/spool/mail.
You can look at the documentation for more examples.
In:
File.rename(name, new_name)
name is never defined prior to its attempted use.
Perhaps p is supposed to be name, or name should be p?
With that assumption I'd write the loop something like:
pic_names.each_with_index do |name, pic_number|
print '.'
new_name = "#{ batch_name }#{ 1 + pic_number }.jpg"
File.rename(name, File.join(File.dirname(name), new_name))
end
File.join(File.dirname(name), new_name) is important. You have to refer to the same path in both the original and new filenames, otherwise the file will be moved to a new location, which would be wherever the current-working-directory points to. That's currently masked by your use of chdir at the start, but, without that, you'd wonder where your files went.

Resources