Can a Ruby Script Tell What Directory It's In

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; or
  • File.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



Leave a reply



Submit