Can a Ruby script tell what directory it’s in?
For newer versions of Ruby, try:
__dir__
For older versions of Ruby (< 2.0), the script being run can be found using:
File.dirname(__FILE__)
- relative path; orFile.expand_path(File.dirname(__FILE__))
- the absolute path.
Note: Using __dir__
will return the script path even after a call to Dir.chdir
; whereas, using the older syntax may not return the path to the script.
How do I get the name of the current directory in Ruby?
dirname = File.basename(Dir.getwd)
File.basename()
returns the base name even when its argument is the path of a directory.
To get absolute path, Dir.pwd seems to do the trick.
How to find the full path that was used to run a Ruby script
You can access that value as $0
inside your script.
How to access calling folder when Ruby script is run as executable?
If I understand you right, you should be able to use this to get the directory the ruby script is in regardless of how you invoke it.
File.dirname(File.expand_path(__FILE__))
If I make a simple script that simply puts
the above and place it in ~/tmp/foo.rb
this is the output. My prompt is my current directory followed by a '$'. In every case the same value is returned.
~/tmp $ ruby foo.rb
/Users/philip/tmp
~ $ ruby tmp/foo.rb
/Users/philip/tmp
~ $ ruby /Users/philip/tmp/foo.rb
/Users/philip/tmp
~ $ cd /
/ $ ruby /Users/philip/tmp/foo.rb
/Users/philip/tmp
Test if the current directory is inside a Rails project (bash)
Upon further investigation, I was able to dig into the rails
command itself and based a solution on part of the railties
gem (<railties>/lib/rails/script_rails_loader.rb
):
#!/usr/bin/env ruby
require 'pathname'
SCRIPT_RAILS = File.join('script', 'rails')
def self.in_rails_application?
File.exists?(SCRIPT_RAILS)
end
def self.in_rails_application_subdirectory?(path = Pathname.new(Dir.pwd))
File.exists?(File.join(path, SCRIPT_RAILS)) || !path.root? && in_rails_application_subdirectory?(path.parent)
end
if in_rails_application? || in_rails_application_subdirectory?
exit(0)
else
exit(1)
end
How to find the file path of file that is not the current file in ruby
A simple Dir['c:/**/test.txt']
will give you an array of all the test.txt files on your c: drive.
Dir['c:/**/*.txt']
will give you all files with the .txt extension (could be a lot)
But in windows there is the exellent tool search everything, it also has a command line version whose output you can capture in a Ruby script. On a large folder or drive this is going to be a lot faster that "Dir" or "Find" which can also be used. I once did that, here the method that does that, you will need to install both everything and the command line extension.
require 'win32ole'
ES = 'C:\****\es\es.exe' # path to command line of Search Everything
def filelist path
command = %Q{"#{ES}" -n 60 folder: -p #{path.join(" ").gsub('/','\\')}}
list = []
IO.popen(command+" 2>&1") do |pipe|
while lijn = pipe.gets
list << lijn.chomp
end
end
list.join(',')
end
EDIT
For Gary, a methods that shells out to the OS, I use this in a Sync tool of me that needs the last modified time of a file and getting that with the Ruby methods is way too slow for more than a thousand files.
It returns a hash which key is the path and the value is the last modified date of the file. It skips some filesAdapt as you wish.
def list_files path
folder, collection = "", {}
IO.popen("dir /s /a:-d #{path}\\*.* 2>&1").each_line do |line|
case line
when /$RECYCLE.BIN|AlbumArt/ # skip these
when /\d{8}T\d{6}/ # skip these
when /desktop.ini|thumbs.db|sync_hist$/ # skip these
when /^(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2})/
modified = $1
filename = line[36..-1].chomp
collection["#{folder}\\#{filename}".downcase] = DateTime::strptime(modified, "%d/%m/%Y %H:%M") rescue nil
when /^ Map van / # Dutch for Folder of (my OS is in Dutch)
folder = line[9..-1].chomp[path.length..-1]
end
end
collection
end
EDIT2
Today I had to use one of those methods because my folder I had to process contained some 30000 files and the waittime before something happened with the normal Ruby Dir was just too long and my system froze while the script executed.
I remembered this answer so I thought to include the results.
I did some benchmarks and the clear winner is de dir from windows self.
There were some errors and extras in the methods I first published but I'm not going to change them because the answer was acceptedl like that and the extra (eg modified time) could be usefull.
In stead here the three ways I tested with their benchmarks and a fourth using lazy to see what changes (not much).
require 'benchmark'
STDOUT.sync = true
start_folder = 'c:/jpg'
def ruby_dir folder
ruby_folder = folder.gsub('\\','/')
files = []
Dir.glob("#{ruby_folder}/**/*").each do |file|
files << file if File.file? file
end
files
end
def ruby_dir_with_lazy folder
ruby_folder = folder.gsub('\\','/')
files = []
Dir.glob("#{ruby_folder}/**/*").lazy.each do |file|
if File.file? file
files << file
end
end
files
end
def os_dir path
win_path = path.gsub('/','\\')
files = []
folder = win_path
IO.popen("dir /s /a:-d #{win_path}\\*.* 2>&1").each_line do |line|
case line
when /^(\d{2}\/\d{2}\/\d{4} \d{2}:\d{2})/
filename = line[36..-1].chomp
files << "#{folder}\\#{filename}"
when /^ Map van / # Dutch for Folder of (my OS is in Dutch)
folder = line[9..-1].chomp
end
end
files
end
def es_dir path
win_path = path.gsub('/','\\')
files = []
es = 'c:\everything\es\es.exe' # path to command line of Search Everything
command = %Q{"#{es}" -p #{win_path}}
IO.popen(command+" 2>&1").each_line do |line|
files << line
end
files
end
Benchmark.bm do |x|
x.report("ruby_dir ") { 3.times { ruby_dir(path) } }
x.report("ruby_dir_with_lazy") { 3.times { ruby_dir_with_lazy(path) } }
x.report("os_dir ") { 3.times { os_dir(path) } }
x.report("es_dir ") { 3.times { es_dir(path) } }
end
os_dir gives a 26 times as fast result as the standard Ruby Dir
ruby_dir 1.747000 18.626000 20.373000 ( 20.397883)
ruby_dir_with_lazy 1.482000 18.799000 20.281000 ( 20.340853)
os_dir 0.608000 0.124000 0.732000 ( 0.786640)
es_dir 1.202000 1.202000 2.404000 ( 5.905093)
How to check if a given directory exists in Ruby
If it matters whether the file you're looking for is a directory and not just a file, you could use File.directory?
or Dir.exist?
. This will return true only if the file exists and is a directory.
As an aside, a more idiomatic way to write the method would be to take advantage of the fact that Ruby automatically returns the result of the last expression inside the method. Thus, you could write it like this:
def directory_exists?(directory)
File.directory?(directory)
end
Note that using a method is not necessary in the present case.
How to get the name of the folders from the file name in Ruby?
The Pathname
class from the Ruby standard library can be used to break down paths into their constituent parts:
require 'pathname'
path = Pathname.new("E:/aaa/bbb/ccc/filename.jpg")
path.dirname.each_filename.drop(1) # ["aaa", "bbb", "ccc"]
Related Topics
How to Recursively Require All Files in a Directory in Ruby
Rvm Install: Ruby Installation Error
Rails Sort Tags by Most Used (Tag.Posts.Count)
How to Generate PDF from Markdown Using Pure Ruby
Cannot Load Such File -- 1.9/Bcrypt_Ext (Loaderror)
Single Table Inheritance or Class Table Inheritance
In Ruby/Rails, How to Encode/Escape Special Characters in Urls
Ruby Symbols VS Strings in Hashes
How to Generate Coordinates in Between Two Known Points
Do You Know an Alternative Ctags Generator for Ruby
Call Task More Than Once in Rails 3 Generator
Rails 3.1 Actioncontroller::Routingerror (No Route Matches [Get] "/Assets/Rails.Png"):
Determine If One Array Contains All Elements of Another Array
Converting Date Object to Timewithzone