I use JRuby in SikuliX IDE to get list of folders and its subfolders recursively and store its absolute paths(which may contains also dotted characters) in an array. I tried to use following code:
records = Dir.glob 'C:/_private/Files/**/*/'
I got error message:
[error] SyntaxError ( invalid multibyte char (UTF-8) )
Expected output:
C:/_private/Files/dir1
C:/_private/Files/dir1/subdir1
C:/_private/Files/dir1/subdir2
C:/_private/Files/dir2
C:/_private/Files/dir2/subdir1
C:/_private/Files/dir2/subdir2
please check new stuff it producing expected result -
records = Dir.glob('/E:/ISSUE_Folder/**/*.*')
records.each do |item|
puts File.dirname(item)
end
As you see its going to every folder and sub folder
My rails app have config folder & it have number of files & subfolders, so getting only folders in config,
I used ap below provided by awesome_print gem
> ap Dir.glob "#{Rails.root}/config/**/"
[
[0] "/home/ray/projects/example_app/config/",
[1] "/home/ray/projects/example_app/config/initializers/",
[2] "/home/ray/projects/example_app/config/locales/",
[3] "/home/ray/projects/example_app/config/environments/"
]
I have test folder inside config/locales/, It is also got by following query.
> ap Dir.glob "#{Rails.root}/config/**/**/"
[
[0] "/home/ray/projects/example_app/config/",
[1] "/home/ray/projects/example_app/config/initializers/",
[2] "/home/ray/projects/example_app/config/locales/",
[3] "/home/ray/projects/example_app/config/locales/test/",
[4] "/home/ray/projects/example_app/config/environments/"
]
For further search for sub-folders on third level hierarchy, I will use "#{Rails.root}/config/**/**/**/"
Update:
You can try with following for windows,
irb(main):022:0> Dir.glob("D:/sd/*/") # first hierarchy
=> ["D:/sd/df/", "D:/sd/dff/"]
irb(main):023:0> Dir.glob("D:/sd/*")
=> ["D:/sd/351px-Nvidia_logo.png", "D:/sd/df", "D:/sd/dff"]
irb(main):024:0> Dir.glob("D:/sd/*/*/") # second hierarchy
=> ["D:/sd/dff/ty/"]
irb(main):025:0> Dir.glob("D:/sd/*/*")
=> ["D:/sd/df/351px-Nvidia_logo2.png", "D:/sd/dff/ty"]
You can further get result by adding first and second hierarchy (commented in above) subfolders
Maybe your JRuby be using less than or equal to ruby 1.9
In Ruby 1.9, the header in your file needs to indicate encoding format.
Add this line at top
# encoding: UTF-8
Related
I have a simple sinatra app uses yaml files to handle data. One of the feature is an User can vote or veto for a Question. The vote feature works fine, but I met some weird things when implementing the veto feature.
Briefly saying:
when a question's current votes_count is positive (>= 1), the number will decrease correctly
but when a question's current votes_count is zero or negative, the number will successfully decrease in the data hash, but after dump data hash into the yaml file, negative becomes positive.
This is the yaml file for Question:
'1': !ruby/hash:Sinatra::IndifferentHash
title: " Best way to require all files from a directory in ruby?"
description: What's the best way to require all files from a directory in ruby ?
user_id: '3'
votes_count: 0
# other user information
This is the route handler relates to veto feature:
post "/questions/:id/veto" do
check_vote_validity_for_question(params[:id])
#question = Question.find_by(:id, params[:id])
#question.votes_count = (#question.votes_count.to_i - 1)
Question.update(params[:id], votes_count: #question.votes_count )
# omit user related code
end
This is the update method:
def self.update(id, attrs)
data = load_data_of(data_name)
# binding.pry
obj_info = data[id]
attrs.each do |k, v|
v = v.to_s if v.is_a?(Array)
obj_info[k] = v
end
# binding.pry
File.open(File.join(data_path, "#{data_name.to_s}.yaml"), "w+") do |f|
f.write(Psych.dump(data).delete("---"))
end
end
If I pause the program inside update method before and after update the data hash, it shows the value of votes_count was set correctly.
Before:
[1] pry(Question)> data
=> {"1"=>
{"title"=>" Best way to require all files from a directory in ruby?",
"description"=>"What's the best way to require all files from a directory in ruby ?",
"user_id"=>"3",
"votes_count"=>0},
After:
[1] pry(Question)> data
=> {"1"=>
{"title"=>" Best way to require all files from a directory in ruby?",
"description"=>"What's the best way to require all files from a directory in ruby ?",
"user_id"=>"3",
"votes_count"=>-1},
The value of the key"votes_count" in data hash is -1 after updating, but after I dumping the data hash into yaml file, the value of "votes_count" of the user in the yaml file became 1. And if the value in hash is -2, it will become 2 in the yaml file.
I tried making a hash which has a negative value in irb, then dump it into a yaml file, things work ok. I have no idea what happened. Could anybody help me?
It looks the problem in the line
f.write(Psych.dump(data).delete("---"))
You delete -.
For example
"-1".delete("---") #=> "1"
I am struggling to iterate tasks with files in Ruby.
(Purpose of the program = every week, I have to save 40 pdf files off the school system containing student scores, then manually compare them to last week's pdfs and update one spreadsheet with every student who has passed their target this week. This is a task for a computer!)
I have converted a pdf file to text, and my program then extracts the correct data from the text files and turns each student into an array [name, score, house group]. It then checks each new array against the data in the csv file, and adds any new results.
My program works on a single pdf file, because I've manually typed in:
f = File.open('output\agb summer report.txt')
agb = []
f.each_line do |line|
agb.push line
end
But I have a whole folder of pdf files that I want to run the program on iteratively. I've also had problems when I try to write each result to a new-named file.
I've tried things with variables and code blocks, but I now don't think you can use a variable in that way?
Dir.foreach('output') do |ea|
f = File.open(ea)
agb = []
f.each_line do |line|
agb.push line
end
end
^ This doesn't work. I've also tried exporting the directory names to an array, and doing something like:
a.each do |ea|
var = '\'output\\' + ea + '\''
f = File.open(var)
agb = []
f.each_line do |line|
agb.push line
end
end
I think I'm fundamentally confused about the sorts of object File and Dir are? I've searched a lot and haven't found a solution yet. I am fairly new to Ruby.
Anyway, I'm sure this can be done - my current backup plan is to copy my program 40 times with different details, but that sounds absurd. Please offer thoughts?
You're very close. Dir.foreach() will return the name of the files whereas File.open() is going to want the path. A crude example to illustrate this:
directory = 'example_directory'
Dir.foreach(directory) do |file|
# Assuming Unix style filesystem, skip . and ..
next if file.start_with? '.'
# Simply puts the contents
path = File.join(directory, file)
puts File.read(path)
end
Use Globbing for File Lists
You need to use Dir#glob to get your list of files. For example, given three PDF files in /tmp/pdf, you collect them with a glob like so:
Dir.glob('/tmp/pdf/*pdf')
# => ["/tmp/pdf/1.pdf", "/tmp/pdf/2.pdf", "/tmp/pdf/3.pdf"]
Dir.glob('/tmp/pdf/*pdf').class
# => Array
Once you have a list of filenames, you can iterate over them with something like:
Dir.glob('/tmp/pdf/*pdf').each do |pdf|
text = %x(pdftotext "#{pdf}")
# do something with your textual data
end
If you're on a Windows system, then you might need a gem like pdf-reader or something else from Ruby Toolbox that suits you better to actually parse the PDF. Regardless, you should use globbing to create a file list; what you do after that depends on what kind of data the file actually holds. IO#read and descendants like File#read are good places to start.
Handling Text Files
If you're dealing with text files rather than PDF files, then something like this will get you started:
Dir.glob('/tmp/pdf/*txt').each do |text|
# Do something with your textual data. In this case, just
# dump the files to standard output.
p File.read(text)
end
You can use Dir.new("./") to get all the files in the current directory
so something like this should work.
file_names = Dir.new "./"
file_names.each do |file_name|
if file_name.end_with? ".txt"
f = File.open(file_name)
agb = []
f.each_line do |line|
agb.push line
end
end
end
btw, you can just use agb = f.to_a to convert the file contents into an array were each element is a line from the file.
file_names = Dir.new "./"
file_names.each do |file_name|
if file_name.end_with? ".txt"
f = File.open file_name
agb = f.to_a
# do whatever processing you need to do
end
end
if you assign your target folder like this /path/to/your/folder/*.txt it will only iterate over text files.
2.2.0 :009 > target_folder = "/home/ziya/Desktop/etc3/example_folder/*.txt"
=> "/home/ziya/Desktop/etc3/example_folder/*.txt"
2.2.0 :010 > Dir[target_folder].each do |texts|
2.2.0 :011 > puts texts
2.2.0 :012?> end
/home/ziya/Desktop/etc3/example_folder/ex4.txt
/home/ziya/Desktop/etc3/example_folder/ex3.txt
/home/ziya/Desktop/etc3/example_folder/ex2.txt
/home/ziya/Desktop/etc3/example_folder/ex1.txt
iteration over text files is ok
2.2.0 :002 > Dir[target_folder].each do |texts|
2.2.0 :003 > File.open(texts, 'w') {|file| file.write("your content\n")}
2.2.0 :004?> end
results
2.2.0 :008 > system ("pwd")
/home/ziya/Desktop/etc3/example_folder
=> true
2.2.0 :009 > system("for f in *.txt; do cat $f; done")
your content
your content
your content
your content
The code below gets a list of images from the public/images directory, creates an array of hashes and converts it to JSON then returns to the caller.
The code works perfectly on the local host - I get the list of image names as needed.
I then uploaded the code to my VPS and ran it on the same environment, running on thin, and nothing is returned at all. No matter what I change, either the path or method for getting filenames, like using glob instead of just Dir, nothing works that I tried.
Here is the code in the route I call from the client-side JavaScript using Ajax:
# get all images
get '/debug/posts/images/' do
puts '>> debug > posts > images > get'
all_images = Array.new
# build substitute prefix path
uri = URI(request.url)
prefix ='http://' + uri.host
if request.port
prefix += ':' + request.port.to_s
end
prefix += '/content/'
begin
content_type :json
# get list of images
pics = Dir['public/images/*']
pics.map { |pic|
# build hash for use with tinyMCE
pic.split('/')
pic_hash = {:title => File.basename(pic).to_s, :value => prefix + File.basename(pic).to_s}
all_images.push(pic_hash)
}
# convert to json
pic_json = JSON.generate(all_images)
body(pic_json)
rescue Sequel::Error => e
puts e.message
status(400).to_json
end
end
I get an array of values back running on the localhost:
[ {title: "bear-love.jpg"value: "/content/bear-love.jpg"}, {title: "bear-love2.jpg"value: "/content/bear-love2.jpg"}...]
I get an empty array from the VPS:
[]
Check that the server is being run as a user who has permission to read and execute public/images
verify that public/images exists
verify that public/images is where you think it is.
Turns out that it's easier to get the current path on the server and simply get a list of the image filenames I needed that way and just add my prefix path for use from the browser.
I'm working on a program to download a video from YouTube, convert it to MP3 and create a directory structure for the files.
My code is:
FileUtils.cd("#{$musicdir}/#{$folder}") do
YoutubeDlhelperLibs::Downloader.get($url)
if File.exists?('*.mp4')
puts 'Remove unneeded tempfile'
Dir['*.mp4'].each do |waste|
File.delete(waste)
end
else
puts 'Temporary file already deleted'
end
Dir['*.m4a'].each do |rip|
rip.to_s
rip.split
puts 'Inside the function'
puts rip
end
end
The first one goes to the already created music folder. Inside that I'm executing get. After that I have two files in the directory: "xyz.mp4" and "xyz.m4a".
I would like to fetch the filename without the extension so I can handle both files differently.
I'm using an array, but an array for just one match sounds crazy for me.
Has anyone another idea?
You can use the following functions for your purpose:
path = "/path/to/xyz.mp4"
File.basename(path) # => "xyz.mp4"
File.extname(path) # => ".mp4"
File.basename(path, ".mp4") # => "xyz"
File.basename(path, ".*") # => "xyz"
File.dirname(path) # => "/path/to"
I have a simple constant hash with string keys defined:
MY_CONSTANT_HASH = {
'key1' => 'value1'
}
Now, I've noticed that encoding.name on the key is US-ASCII. However, Encoding.default_internal is set to UTF-8 beforehand. Why is it not being properly encoded? I can't force_encoding later, because the object is frozen at that point, so I get this error:
can't modify frozen String
P.S.: I'm using ruby 1.9.3p0 (2011-10-30 revision 33570).
The default internal and external encodings are aimed at IO operations:
CSV
File data read from disk
File names from Dir
etc...
The easiest thing for you to do is to add a # encoding=utf-8 comment to tell Ruby that the source file is UTF-8 encoded. For example, if you run this:
# encoding=utf-8
H = { 'this' => 'that' }
puts H.keys.first.encoding
as a stand-alone Ruby script you'll get UTF-8, but if you run this:
H = { 'this' => 'that' }
puts H.keys.first.encoding
you'll probably get US-ASCII.