I'm having trouble with the following piece of code where user input of directory name is used to fetch list of files of a particular extension on a windows machine
puts "Enter the name of directory where files exist : "
directory = gets.chomp
csv_files = Dir.glob("#{directory}/*.csv")
Regardless of the directory input ( the directory has .csv files), the last line returns an empty array.
ruby version - ruby 2.0.0p598 (2014-11-13) [i386-mingw32]
Adding additional info asked in comments
PS C:\test> irb
irb(main):001:0> directory = gets.chomp
C:\test
=> "C:\\test"
irb(main):002:0> directory
=> "C:\\test"
irb(main):003:0> Dir.glob("#{directory}/*.csv")
=> []
irb(main):004:0> Dir.glob("#{directory}/*.*")
=> []
irb(main):005:0> Dir.glob("C:/" + directory + "/*.csv")
=> []
irb(main):006:0> Dir.glob("C:/test/*")
=> ["C:/test/test_csv.csv"]
irb(main):007:0> Dir.entries(directory)
=> [".", "..","test_csv.csv"]
irb(main):010:0> Dir.glob('./*.csv')
=> ["./test_csv.csv"]
irb(main):011:0>
Found the solution as below.
Use File.expand_path method to convert the input string into a standard ruby file path.
puts "Enter the name of directory where files exist : "
directory = File.expand_path(gets.chomp)
csv_files = Dir.glob("#{directory}/*.csv")
Related
Previously I was using Ruby 1.8 and my irb command prompt used to look like this:
Air ~: irb
>> a = 1
=> 1
>> b = 2
=> 2
>> a + b
=> 3
I installed rvm (and Ruby 1.9.2) and now my irb command prompt looks like this:
Air ~: irb
ruby-1.9.2-p180 :001 > a = 1
=> 1
ruby-1.9.2-p180 :002 > b = 2
=> 2
ruby-1.9.2-p180 :003 > a + b
=> 3
Is there a way to remove the ruby-1.9.2-p180 :001 from the command line?
The irb man page has a section on "Customizing prompt". Here's mine for example:
IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_I => ">> ",
:PROMPT_S => "%l>> ",
:PROMPT_C => ".. ",
:PROMPT_N => ".. ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :CUSTOM
IRB.conf[:AUTO_INDENT] = true
To use this, add it to your ~/.irbrc file (creating it if it doesn't exist.)
In your ~/.irbrc, simply add
IRB.conf[:PROMPT_MODE] = :SIMPLE
When you would usually run the irb command, try running irb --simple-prompt instead. That greatly shortens the prompt and makes it easier to understand.
irb --simple-prompt
saw this in Lynda.com
To avoid giving the prompt you wish on the command line all the time, you can configure the prompt via the ~/.irbrc config file:
$ echo "IRB.conf[:PROMPT_MODE] = :DEFAULT" > ~/.irbrc
$ irb
irb(main):001:0> quit
$ echo "IRB.conf[:PROMPT_MODE] = :SIMPLE" > ~/.irbrc
$ irb
>> quit
$
Whoever want to add a prompt timestamp, this isn't possible yet (check "special strings" section), so I implemented it in a monkey-patchy way:
module IrbTimePrompt
def prompt(prompt, ltype, indent, line_no)
# I used %T as time format, but you could use whatever you want to.
# Check https://apidock.com/ruby/Time/strftime for more options
p = prompt.dup.gsub(/%t/, Time.new.strftime('%T'))
super(p, ltype, indent, line_no)
end
end
module IRB
class Irb
prepend IrbTimePrompt
end
end
Now, add this to your lib/ project folder (in case is a Rails project, ensure lib/ is part of config.autoload_paths in config/application.rb) or in a more aggresive way (not recommended), look for lib/irb.rb file in your local ruby instance and in def prompt method, add a new when condition to the method, like:
when "t"
Time.now.strftime('%-d-%-m %T%Z')
then in your .irbrc file (it could be located in your home folder or root project folder) you could modify your prompt. I'm adding my current prompt, but please adjust it to your needs:
def rails_prompt
# This is my base prompt, displaying line number and time
def_prompt = '[%01n][%t]'
# Maybe you're only running as `irb` an not `rails console`, so check first
# if rails is available
if defined? Rails
app_env = Rails.env[0...4]
if Rails.env.production?
puts "\n\e[1m\e[41mWARNING: YOU ARE USING RAILS CONSOLE IN PRODUCTION!\n" \
"Changing data can cause serious data loss.\n" \
"Make sure you know what you're doing.\e[0m\e[22m\n\n"
app_env = "\e[31m#{app_env}\e[0m" # red
else
app_env = "\e[32m#{app_env}\e[0m" # green
end
def_prompt << "(\e[1m#{app_env}\e[22m)" # bold
end
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:WITH_TIME] = {
PROMPT_I: "#{def_prompt}> ",
PROMPT_N: "#{def_prompt}| ",
PROMPT_C: "#{def_prompt}| ",
PROMPT_S: "#{def_prompt}%l ",
RETURN: "=> %s\n",
AUTO_INDENT: true,
}
IRB.conf[:PROMPT_MODE] = :WITH_TIME
end
rails_prompt
Then start irb or rails console and check the awesomeness:
[1][13:01:15](deve)> 'say hello to your new prompt'
=> "say hello to your new prompt"
[2][13:01:23](deve)>
See this note about IRB prompt in RVM.
Note that you can create a .irbrc file in your home folder for various settings for IRB.
For example, see "Configuring the Prompt" in this document
You can also puts IRB.conf[:PROMPT_MODE] or puts IRB.conf to see all the various settings currently in effect. For example, the :PROMPT_MODE is probably set to "RVM" in your case.
How can I read/write a FILE with filename containing Forward slashes (/)?
This is what I'm trying to do -
filename = "A/B/C"
full_path = "#{Rails.root}/public/barcodes/#{filename}.png"
File.open(full_path, 'w') { |f| f.write #barcode_png.to_png(:margin => 3, :xdim => 2,:ydim => 2, :height => 100) }
Everytime I execute this, Ruby tries to find a folder by name A, B and C instead of writing a file "A/B/C"
Any thoughts on how to make this work?
Thanks!
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"
When using Tempfile Ruby is creating a file with a thread-safe and inter-process-safe name. I only need a file name in that way.
I was wondering if there is a more straight forward approach way than:
t = Tempfile.new(['fleischwurst', '.png'])
temp_path = t.path
t.close
t.unlink
Dir::Tmpname.create
You could use Dir::Tmpname.create. It figures out what temporary directory to use (unless you pass it a directory). It's a little ugly to use given that it expects a block:
require 'tmpdir'
# => true
Dir::Tmpname.create(['prefix-', '.ext']) {}
# => "/tmp/prefix-20190827-1-87n9iu.ext"
Dir::Tmpname.create(['prefix-', '.ext'], '/my/custom/directory') {}
# => "/my/custom/directory/prefix-20190827-1-11x2u0h.ext"
The block is there for code to test if the file exists and raise an Errno::EEXIST so that a new name can be generated with incrementing value appended on the end.
The Rails Solution
The solution implemented by Ruby on Rails is short and similar to the solution originally implemented in Ruby:
require 'tmpdir'
# => true
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-wyouwg-YOUR_SUFFIX"
File.join(Dir.tmpdir, "YOUR_PREFIX-#{Time.now.strftime("%Y%m%d")}-#{$$}-#{rand(0x100000000).to_s(36)}-YOUR_SUFFIX")
=> "/tmp/YOUR_PREFIX-20190827-1-140far-YOUR_SUFFIX"
Dir::Tmpname.make_tmpname (Ruby 2.5.0 and earlier)
Dir::Tmpname.make_tmpname was removed in Ruby 2.5.0. Prior to Ruby 2.4.4 it could accept a directory path as a prefix, but as of Ruby 2.4.4, directory separators are removed.
Digging in tempfile.rb you'll notice that Tempfile includes Dir::Tmpname. Inside you'll find make_tmpname which does what you ask for.
require 'tmpdir'
# => true
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname("prefix-", nil))
# => "/tmp/prefix-20190827-1-dfhvld"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], nil))
# => "/tmp/prefix-20190827-1-19zjck1.ext"
File.join(Dir.tmpdir, Dir::Tmpname.make_tmpname(["prefix-", ".ext"], "suffix"))
# => "/tmp/prefix-20190827-1-f5ipo7-suffix.ext"
Since Dir::Tmpname.make_tmpname was removed in Ruby 2.5.0, this one falls back to using SecureRandom:
require "tmpdir"
def generate_temp_filename(ext=".png")
filename = begin
Dir::Tmpname.make_tmpname(["x", ext], nil)
rescue NoMethodError
require "securerandom"
"#{SecureRandom.urlsafe_base64}#{ext}"
end
File.join(Dir.tmpdir, filename)
end
Since you only need the filename, what about using the SecureRandom for that:
require 'securerandom'
filename = "#{SecureRandom.hex(6)}.png" #=> "0f04dd94addf.png"
You can also use SecureRandom.alphanumeric
I found the Dir:Tmpname solution did not work for me. When evaluating this:
Dir::Tmpname.make_tmpname "/tmp/blob", nil
Under MRI Ruby 1.9.3p194 I get:
uninitialized constant Dir::Tmpname (NameError)
Under JRuby 1.7.5 (1.9.3p393) I get:
NameError: uninitialized constant Dir::Tmpname
You might try something like this:
def temp_name(file_name='', ext='', dir=nil)
id = Thread.current.hash * Time.now.to_i % 2**32
name = "%s%d.%s" % [file_name, id, ext]
dir ? File.join(dir, name) : name
end
Previously I was using Ruby 1.8 and my irb command prompt used to look like this:
Air ~: irb
>> a = 1
=> 1
>> b = 2
=> 2
>> a + b
=> 3
I installed rvm (and Ruby 1.9.2) and now my irb command prompt looks like this:
Air ~: irb
ruby-1.9.2-p180 :001 > a = 1
=> 1
ruby-1.9.2-p180 :002 > b = 2
=> 2
ruby-1.9.2-p180 :003 > a + b
=> 3
Is there a way to remove the ruby-1.9.2-p180 :001 from the command line?
The irb man page has a section on "Customizing prompt". Here's mine for example:
IRB.conf[:PROMPT][:CUSTOM] = {
:PROMPT_I => ">> ",
:PROMPT_S => "%l>> ",
:PROMPT_C => ".. ",
:PROMPT_N => ".. ",
:RETURN => "=> %s\n"
}
IRB.conf[:PROMPT_MODE] = :CUSTOM
IRB.conf[:AUTO_INDENT] = true
To use this, add it to your ~/.irbrc file (creating it if it doesn't exist.)
In your ~/.irbrc, simply add
IRB.conf[:PROMPT_MODE] = :SIMPLE
When you would usually run the irb command, try running irb --simple-prompt instead. That greatly shortens the prompt and makes it easier to understand.
irb --simple-prompt
saw this in Lynda.com
To avoid giving the prompt you wish on the command line all the time, you can configure the prompt via the ~/.irbrc config file:
$ echo "IRB.conf[:PROMPT_MODE] = :DEFAULT" > ~/.irbrc
$ irb
irb(main):001:0> quit
$ echo "IRB.conf[:PROMPT_MODE] = :SIMPLE" > ~/.irbrc
$ irb
>> quit
$
Whoever want to add a prompt timestamp, this isn't possible yet (check "special strings" section), so I implemented it in a monkey-patchy way:
module IrbTimePrompt
def prompt(prompt, ltype, indent, line_no)
# I used %T as time format, but you could use whatever you want to.
# Check https://apidock.com/ruby/Time/strftime for more options
p = prompt.dup.gsub(/%t/, Time.new.strftime('%T'))
super(p, ltype, indent, line_no)
end
end
module IRB
class Irb
prepend IrbTimePrompt
end
end
Now, add this to your lib/ project folder (in case is a Rails project, ensure lib/ is part of config.autoload_paths in config/application.rb) or in a more aggresive way (not recommended), look for lib/irb.rb file in your local ruby instance and in def prompt method, add a new when condition to the method, like:
when "t"
Time.now.strftime('%-d-%-m %T%Z')
then in your .irbrc file (it could be located in your home folder or root project folder) you could modify your prompt. I'm adding my current prompt, but please adjust it to your needs:
def rails_prompt
# This is my base prompt, displaying line number and time
def_prompt = '[%01n][%t]'
# Maybe you're only running as `irb` an not `rails console`, so check first
# if rails is available
if defined? Rails
app_env = Rails.env[0...4]
if Rails.env.production?
puts "\n\e[1m\e[41mWARNING: YOU ARE USING RAILS CONSOLE IN PRODUCTION!\n" \
"Changing data can cause serious data loss.\n" \
"Make sure you know what you're doing.\e[0m\e[22m\n\n"
app_env = "\e[31m#{app_env}\e[0m" # red
else
app_env = "\e[32m#{app_env}\e[0m" # green
end
def_prompt << "(\e[1m#{app_env}\e[22m)" # bold
end
IRB.conf[:PROMPT] ||= {}
IRB.conf[:PROMPT][:WITH_TIME] = {
PROMPT_I: "#{def_prompt}> ",
PROMPT_N: "#{def_prompt}| ",
PROMPT_C: "#{def_prompt}| ",
PROMPT_S: "#{def_prompt}%l ",
RETURN: "=> %s\n",
AUTO_INDENT: true,
}
IRB.conf[:PROMPT_MODE] = :WITH_TIME
end
rails_prompt
Then start irb or rails console and check the awesomeness:
[1][13:01:15](deve)> 'say hello to your new prompt'
=> "say hello to your new prompt"
[2][13:01:23](deve)>
See this note about IRB prompt in RVM.
Note that you can create a .irbrc file in your home folder for various settings for IRB.
For example, see "Configuring the Prompt" in this document
You can also puts IRB.conf[:PROMPT_MODE] or puts IRB.conf to see all the various settings currently in effect. For example, the :PROMPT_MODE is probably set to "RVM" in your case.