As an example:
Dir[File.dirname(__FILE__) + "/support/**/*.rb"].each { |f| require f }
This is how RSpec requires all of the ruby files in the support directory and all subdirectories. I know this has to do with "/**/*". What does this mean in Ruby? How does it work?
File.dirname(__FILE__) is the directory where the file is. ** and * are UNIX wildcards. Adding "/support/**/*.rb to the directory points to any file that ends with .rb, which is under an arbitrary depth under the sub-directory support under that directory.
Passing that to Dir[] gives the array of such files. each iterates over such files, and require loads each file.
i believe that the /**/ part means Any directory , and the *.rb means any file that ends with .rb extention, regardless of it's name.
so, basically, you are getting any .rb file that are in any folder in
#{current_dir}/support/#{any_dir}/#{any_file_with_extention.rb}
Related
e.g. Dir.entries returns an array of strings vs an array containing File or Dir instances.
Most methods on Dir and File types. The instances are aneamic in comparison.
There is no Dir#folders or Dir#files - instead I explicitly
loop over Dir.entries
build the path (File.expand_path) for
each item
check File.directory?
Simple use-cases like get all .svg files in this directory seem to require a number of hoops/loops/checks. Am I using Ruby wrong or does this facet of Ruby seem very un-ruby-ish?
Depending on your needs, File or Dir might do just fine.
When you need to chain commands and (rightfully) think it feels un-ruby-ish to only use class methods with string parameters, you can use Pathname. It is a standard library.
Examples
Dirs and Files
require 'pathname'
my_folder = Pathname.new('./')
dirs, files = my_folder.children.partition(&:directory?)
# dirs is now an Array of Pathnames pointing to subdirectories of my_folder
# files is now an Array of Pathnames pointing to files inside my_folder
All .svg files
If for some reason there might be folders with .svg extension, you can just filter the pathnames returned by Pathname.glob :
svg_files = Pathname.glob("folder/", "*.svg").select(&:file?)
If you want a specific syntax :
class Pathname
def files
children.select(&:file?)
end
end
aDir = Pathname.new('folder/')
p aDir.files.find_all{ |f| f.extname == '.svg' }
Iterating the Directory tree
Pathname#find will help.
Until you open the file it is just a path (string).
To open all .svg files
svgs = Dir.glob(File.join('/path/to/dir', '*.svg'))
On windows case doesn't matter in file paths, but in all unixoid systems (Linux, MacOS...) file.svg is different from file.SVG
To get all .svg files and.SVG files you need File::FNM_CASEFOLD flag.
If you want to get .svg files recursively, you need **/*.svg
svgs = Dir.glob('/path/to/dir/**/*.svg', File::FNM_CASEFOLD)
If you expect directories ending in.svg then filter them out
svgs.reject! { |path| File.directory?(path) }
I'm building a webcrawler and I want it to output to a new file that is timestamped. I've completed what I thought would be the more difficult part but I cannot seem to get it to save to the desktop.
Dir.chdir "~/Desktop"
dirname = "scraper_out"
filename = "#{time}"
Dir.mkdir(dirname) unless File.exists?(dirname)
Dir.chdir(dirname)
File.new(filename, "w")
It errors out on the first line
`chdir': No such file or directory # dir_chdir - ~/Desktop
I've read the documentation on FileUtils, File and cannot seem to find where people change into nested directories from the root.
Edit: I don't think FileUtils understands the ~.
~/ is not recognized by Ruby in this context.
Try:
Dir.chdir ENV['HOME']+"/Desktop"
This might help you
Create a file in a specified directory
Dir.delete("/usr/local/var/lib/trisul/CONTEXT0/meters/oper/SLICE.9stMxh")
causes this error:
Directory not empty - /usr/local/var/lib/trisul/CONTEXT0/meters/oper/SLICE.9stMxh
How to delete a directory even when it still contains files?
Is not possible with Dir (except iterating through the directories yourself or using Dir.glob and deleting everything).
You should use
require 'fileutils'
FileUtils.rm_r "/usr/local/var/lib/trisul/CONTEXT0/meters/oper/SLICE.9stMxh"
When you delete a directory with the Dir.delete, it will also search the subdirectories for files.
Dir.delete("/usr/local/var/lib/trisul/CONTEXT0/meters/oper/SLICE.9stMxh")
If the directory was not empty, it will raise Directory not empty error. For that ruby have FiltUtils.rm_r method which will delete the directory no matter what!
require 'fileutils'
FileUtils.rm_r "/usr/local/var/lib/trisul/CONTEXT0/meters/oper/SLICE.9stMxh"
I use bash directly with the system(*args) command like this:
folder = "~/Downloads/remove/this/non/empty/folder"
system("rm -r #{folder}")
It is not really ruby specific but since bash is simpler in this case I use this frequently to cleanup temporary folders and files. The rm command just removes anything you give it and the -r flag tells it to remove files recursively in case the folder is not empty.
So I want to make a file path relative to the directory it is in, in Ruby.
I have a project, and I want it to be able to find the file no matter what directory the project is unzipped into. (Say the code is run on different machines, for example) I can't figure it out for the life of me.
It seems for requires that I can do this:
require File.dirname(__FILE__) + '/comparison'
What can I do for a file that is in a different directory than my src folder?
Instead of listing,
file = 'C:/whole path/long/very_long/file.txt'
I'd like to say:
file = 'file.txt'
or
file = File.helpful_method + 'file.txt'
file = File.join(File.dirname(__FILE__), '..', 'another_dir', 'file.txt')
Replace '..', 'another_dir' with the relative path segments that reach 'file.txt'.
If you're running Ruby 1.9.2 or later, you can use require_relative instead:
require_relative '../somewhere/file.rb'
This doesn't solve the general problem of referring to files by their relative path, but if all you're doing is requiring the file, it should work.
I'm trying to use RubyZip to package up some files. At the moment I have a method which happily zips on particular directory and sub-directories.
def zip_directory(zipfile)
Dir["#{#directory_to_zip}/**/**"].reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.sub(#directory_to_zip+'/','');
zipfile.add(file_name, file_path)
end
end
However, I want to include a file from a completely different folder. I have a the following method to solve this:
def zip_additional(zipfile)
additional_files.reject{|f| reject_file(f)}.each do |file_path|
file_name = file_path.split('\\').last
zipfile.add(file_name, file_path)
end
end
While the file is added, it also copies the directory structure instead of placing the file at the root of the folder. This is really annoying and makes it more difficult to work with.
How can I get around this?
Thanks
Ben
there is setting to include (or exclude) the full path for zip libraries, check that setting
Turns out it was because the filename had the pull path in. My split didn't work as the path used a / instead of a . With the path removed from the filename it just worked.