Ruby mkdir returns 0 - ruby

I have a Ruby script which sets up a directory which I need some other methods to use to store files. So, I need to be able to pass the directory as a string to some other methods:
To create the directory
results_dir = Dir.mkdir("/results/#{Time.now.strftime('%m-%d-%Y_%H:%M:%S')}")
The problem is that results_dir returns 0, not the string I would expect for the directory that was made: "/results/01-18-2016_14:58:38"
So, when I try to pass this to another method (i.e. my_method(var1, var2, results_dir), it's reading it as:
0/the_file_i_create
How can I pass the actual directory path to my methods?

It's not clear why you expect Dir.mkdir to return the directory name, since the docs explicitly say that Dir.mkdir returns 0:
mkdir( string [, integer] ) → 0
If you need the name of the directory you're creating, put it in a variable before you call Dir.mkdir:
results_dir = "/results/#{Time.now.strftime('%m-%d-%Y_%H:%M:%S')}"
Dir.mkdir(results_dir)
puts results_dir # => /results/01-18-2016_14:58:38
P.S. Avoid using colons (:) in file and directory names. It can cause issues on some systems, including OS X and Windows.

Related

Can't use io.open in home directory - Lua

I'm writing a Mac OS program, and I have the following lines:
os.execute("cd ~/testdir")
configfile = io.open("configfile.cfg", "w")
configfile:write("hello")
configfile:close()
The problem is, it only creates the configfile in the scripts current directory instead of the folder I have just cd' into. I realised this is because I'm using a console command to change directory, then direct Lua code to write the file. To combat this I changed the code to this:
configfile = io.open("~/testdir/configfile.cfg", "w")
However I get the following result:
lua: ifontinst.lua:22: attempt to index global 'configfile' (a nil value)
stack traceback:
ifontinst.lua:22: in main chunk
My question is, what's the correct way to use IO.Open to create a file in a folder I have just created in the users home directory?
I appreciate I'm making a rookie mistake here, so I apologise if you waste your time on me.
You have problems with ~ symbol. In your os.execute("cd ~/testdir") is the shell who interprets the symbol and replaces it by your home path. However, in io.open("~/testdir/configfile.cfg", "w") is Lua who receives the string and Lua doesn't interprets this symbol, so your program tries to open a file in the incorrect folder. One simple solution is to call os.getenv("HOME") and concatenate the path string with your file path:
configfile = io.open(os.getenv("HOME").."/testdir/configfile.cfg", "w")
In order to improve error messages I suggests you to wrap io.open() using assert() function:
configfile = assert( io.open(os.getenv("HOME").."/testdir/configfile.cfg", "w") )

Show error message for every argument that is not defined in Ruby program

I'm creating a program in Ruby for replacing content of multiple files in one directory, and there are four arguments:
dir for defining directory
ext for defining extension
find for defining string to find
replace for defining string that replace string defined as find
Right now, this is start of the program:
dir, ext, find, replace = ARGV
dir, ext, find, replace = ARGV.shift
raise "Missing argument for directory" unless dir
raise "..." unless ext
#etc
However, when I run this program without defining arguments, it shows only first argument that is not defined (directory) with RuntimeError and imediatelly closes program. Is there any different approach for this?
I can offer you such variant:
missing_parameters = ["dir","ext","find","replace"].select{|name| eval(name).nil?}
raise "Missing parameters for #{missing_parameters.join(',')}" unless missing_parameters.empty?
But frankly speaking, i don't like the usage of eval :)

How to navigate two directories up ruby

In Ruby,I have global variable $file_folder that gives me the location of the current config file:
$file_folder = "#{File}"
$file_folder = /repos/.../test-folder/features/support
I need to access a file sitting in a different folder and this folder is two levels up and two levels down. Is there any way to navigate to this target path using the current location?
target path = /repos/..../test-folder/lib/resources
There are two ways to do this (well, there are several, but here are two good ones). First, using File.expand_path:
original_path = "/repos/something/test-folder/features/support"
target_path = File.expand_path("../../lib/resources", original_path)
p target_path
# => "/repos/something/test-folder/lib/resources"
Note that File.expand_path will always return an absolute path, so it's not appropriate if you want to get a relative path back. If you use it, either make sure that the second argument is an absolute path, or, if it's a relative path, that you know what it will expand to (which will depend on the current working directory).
Next, using Pathname#join (which is aliased as Pathname#+):
require "pathname"
original_path = Pathname("/repos/something/test-folder/features/support")
target_path = original_path + "../../lib/resources"
p target_path
# => #<Pathname:/repos/something/test-folder/lib/resources>
You can also use Pathname#parent, but I think it's kind of ugly:
p original_path.parent.parent
# => #<Pathname:/repos/something/test-folder>
p original_path.parent.parent + "lib/resources"
# => #<Pathname:/repos/something/test-folder/lib/resources>
I prefer Pathname because it makes working with paths very easy. In general you can pass the Pathname object to any method that takes a path, but once in awhile a method will balk at anything other than a String, in which case you'll need to cast it as a string first:
p target_path.to_s
# => "/repos/something/test-folder/lib/resources"
P.S. foo = "#{bar}" is an antipattern in Ruby. If bar is already a String you should just use it directly, i.e. foo = bar. If bar isn't already a String (or you're not sure), you should cast it explicitly with to_s, i.e. foo = bar.to_s.
P.P.S. Global variables are a nasty code smell in Ruby. There is almost always a better way to go than using a global variable.

IO.readlines method in ruby behaving wierdly?

It sounds stupid but it has given me 3 hr of head banging...!!
I have created a class method in which I am extracting a file base name (placed in the Root folder). The issue is IO.readlines method is not accepting the file with a base name returned from the fetching. It returns error:
./lib/fileCheck.rb:36:in `readlines': No such file or directory - (Errno::ENOENT)
But it works as soon as I manually enter the file base name in readlines. Here is the class method:
class FileCheck
def self.read_file
file = File.basename(Dir[File.join(File.expand_path('../.'), "*.txt")].to_s)
file = IO.readlines(file)
return file
end
end
No result, but as soon as I place the file name manually, it works perfectly.
def self.read_file
#file = File.basename(Dir[File.join(File.expand_path('../.'), "*.txt")].to_s)
file = IO.readlines('sample.txt')
return file
end
I check with irb and the statement
File.basename(Dir[File.join(File.expand_path('../.'), "*.txt")].to_s)
is returning a file base name of class String.
Any suggestions?????
it does not matter if you use expand_path or join. you still have a mayor issue in your code:
File.basename(Dir[File.join(File.expand_path('../.'), "*.txt")].to_s)
the Dir[] also known as Dir.glob returns an array! make sure to pick one of the elements instead of calling to_s. you will run into problems when there is more than one file.

Why can't I use "mkdir" with a Pathname object?

I've recently been trying out the Pathname lib, and one thing I want to do is use mkdir to create some directories.
I looked up the documentation and it says it wraps up mkdir but everytime I try to use it I`m getting this error:
irb(main):006:0> p = Pathname.new('/tmp')
=> #<Pathname:/tmp>
irb(main):007:0> a = p.mkdir("123adam")
TypeError: can't convert String into Integer
from /usr/lib/ruby/1.8/pathname.rb:975:in `mkdir'
from /usr/lib/ruby/1.8/pathname.rb:975:in `mkdir'
from (irb):7
from /usr/lib/ruby/1.8/fileutils.rb:1589
Can anyone explain what I`m doing wrong here.
You need to specify the directory you want to create with Pathname and then call mkdir.
This should work:
p = Pathname.new('/tmp/123adam')
p.mkdir
The argument you can supply are the permissions for the new directory.
Out of interest, the reason why you get "can't convert String into Integer" is because Pathname.mkdir is actually a wrapper around Dir.mkdir as follows:
def mkdir(*args) Dir.mkdir(#path, *args) end
The path represented by the Pathname object is passed as the first parameter to Dir.mkdir, followed by any parameters passed to Pathname.mkdir. The second parameter for Dir.mkdir is the numeric access permissions that you would like the directory created to have. Hence in your example "123adam" is being passed to Dir.mkdir where a number is expected.

Resources