slash and backslash in Ruby - ruby

I want to write a application that works in windows and linux. but I have a path problem because windows use "\" and Linux use "/" .how can I solve this problem.
thanks

In Ruby, there is no difference between the paths in Linux or Windows. The path should be using / regardless of environment. So, for using any path in Windows, replace all \ with /. File#join will work for both Windows and Linux. For example, in Windows:
Dir.pwd
=> "C/Documents and Settings/Users/prince"
File.open(Dir.pwd + "/Desktop/file.txt", "r")
=> #<File...>
File.open(File.join(Dir.pwd, "Desktop", "file.txt"), "r")
=> #<File...>
File.join(Dir.pwd, "Desktop", "file.txt")
=> "C/Documents and Settings/Users/prince/Desktop/file.txt"

As long as Ruby is doing the work, / in path names is ok on Windows
Once you have to send a path for some other program to use, especially in a command line or something like a file upload in a browser, you have to convert the slashes to backslashes when running in Windows.
C:/projects/a_project/some_file.rb'.gsub('/', '\\') works a charm. (That is supposed to be a double backslash - this editor sees it as an escape even in single quotes.)
Use something like this just before sending the string for the path name out of Ruby's control.
You will have to make sure your program knows what OS it is running in so it can decide when this is needed. One way is to set a constant at the beginning of the program run, something like this
::USING_WINDOWS = !!((RUBY_PLATFORM =~ /(win|w)(32|64)$/) || (RUBY_PLATFORM=~ /mswin|mingw/))
(I know this works but I didn't write it so I don't understand the double bang...)

Take a look at File.join: http://www.ruby-doc.org/core/classes/File.html#M000031

Use the Pathname class to generate paths which then will be correct on your system:
a_path = Pathname.new("a_path_goes_here")
The benefit of this is that it will allow you to chain directories by using the + operator:
a_path + "another_path" + "and another"
Calling a_path.to_s will then generate the correct path for the system that you are on.

Yes, it's annoying as a windows users to keep replacing those backslashes to slashes and vice-versa if you need the path to copy it to your filemanager, so i do it like his.
It does no harm if you are on Linux or Mac and saves a lot of nuisance in windows.
path = 'I:\ebooks\dutch\_verdelen\Komma'.gsub(/\\/,'/')
Dir.glob("#{path}/**/*.epub").each do |file|
puts file
end

Related

shell cd command in Ruby

Im trying to execute shell commands using ruby, but i cant change directory to PATH with blank spaces.
variable = %x[cd #{ENV["HOME"]}/Virtual\\ VMs/]
This is not working.
Thank you
To be absolutely safe:
path = File.join [ENV["HOME"], 'Virtual VMs']
variable = %x[cd '#{path}']
Please note, that cd has empty output, so to make sure it works one probably wants to do smth like:
path = File.join [ENV["HOME"], 'Virtual VMs']
variable = %x[cd '#{path}' && ls -la]
#⇒ "total 32\ndrwxr-xr-x ....."
What is ist supposed to do? You try to chdir into a directory, but then don't do anything in it. Your variable will be empty in any case. Aside from the fact that it is pointless to do, you can not reliably execute a cd by itself in this way, because it is not an executable file. You can see this if you just execute %x[cd]. You will get an Errno::ENOENT exception.
Maybe you should first describe in a broader context, what you want to achieve with your code. Where would you like to change the working directory? Within the Ruby process - in which case you have to use Dir.chdir - or in the child process - in which case you have to execute some command after the cd.

How to get parent path from filepath?

Let says I've this path:
path = "D:\Google Drive\Samples\Black Octopus Sound\Leviathan\Drums - Kicks\Lev_Kick_A_003.wav"
what's the smart and clean way to get the parent path from this string/path? i.e.:
D:\Google Drive\Samples\Black Octopus Sound\Leviathan\Drums - Kicks\
Couple of ways of doing it as a pure string, either via a regular expression or using split,pop,join.
path = "D:\\Google Drive\\Samples\\Black Octopus Sound\\Leviathan\\Drums - Kicks\\Lev_Kick_A_003.wav"
items = path.split("\\")
items.pop
result = items.join("\\")
puts result
> D:\Google Drive\Samples\Black Octopus Sound\Leviathan\Drums - Kicks
Note I've replaced "\" with "\\" in all cases to escape the slashes
Or in a one liner:
path.split("\\").reverse.drop(1).reverse.join("\\")
The best way is probably Pathname as per other answers, but if you can't use that then string manipulation should work.
Use Pathname:
require 'pathname'
path = "D:\\Google Drive\\Samples/Drums - Kicks\\Lev_Kick_A_003.wav"
Pathname(path).parent
#=> #<Pathname:D:\Google Drive\Samples\Drums - Kicks>
Pathname correctly handles the specific file path syntax of the given operating system.

Why isn't this glob working for a Rake FileList for my server?

How come I get an empty filelist from:
files = FileList.new("#{DEPLOYMENT_PATH}\**\*")
Where DEPLOYMENT_PATH is \\myserver\anndsomepath
How to get a filelist from a server like this? Is this an issue of Ruby/Rake?
UPDATE:
I tried:
files = FileList.new("#{DEPLOYMENT_PATH}\\**\\*")
files = Dir.glob("#{DEPLOYMENT_PATH}\\**\\*")
files = Dir.glob("#{DEPLOYMENT_PATH}\**\*")
UPDATE AGAIN: It works if I put server as:
//myserver/andsomepath
and get files like this:
files = FileList.new("#{DEPLOYMENT_PATH}/**/*")
Ruby' File.join is designed to be your helper when dealing with file paths, by building them in a system-independent way:
File.join('a','b','c')
=> "a/b/c"
So:
DEPLOYMENT_PATH = File.join('', 'myserver', 'andsomepath')
=> "/myserver/andsomepath"
Ruby determines the file path separator by sensing the OS, and is supposed to automatically supply the right value. On Windows XP, Linux and Mac OS it is:
File::SEPARATOR
=> "/"
File.join(DEPLOYMENT_PATH, '**', '*')
=> "/myserver/andsomepath/**/*"
While you can ignore the helper, it is there to make your life easier. Because you are working against a server, you might want to look into File::ALT_SEPARATOR, or just reassigning to SEPARATOR and ignore the warning, letting Ruby do the rest.
What happens if you do
Dir.glob("#{DEPLOYMENT_PATH}\**\*")
Edit: I think Ruby prefers you doing Unix-style slashes, even when you're on Windows. I assume the rationale is that it's better for the same code to work on both Unix and Windows, even if it looks weird on Windows.
tl;dr: If it works with / but not with \, then use what works.
Because:
> "\*" == "*"
=> true
Use "\\**\\*" instead.

System call in Ruby

I'm a beginner in ruby and in programming as well and need help with system call for moving a file from source to destination like this:
system(mv "#{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file}")
Is it possible to do this in Ruby? If so, what is the correct syntax?
system("mv #{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file})
can be replaced with
system("mv", "#{#SOURCE_DIR}/#{my_file}", "#{#DEST_DIR}/#{file}")
which reduces the chances of a command line injection attack.
Two ways
Recommended way
You can use the functions in the File Utils libary see here to move your files e.g
mv(src, dest, options = {})
Options: force noop verbose
Moves file(s) src to dest. If file and dest exist on the different disk
partition, the file is copied instead.
FileUtils.mv 'badname.rb', 'goodname.rb'
FileUtils.mv 'stuff.rb', '/notexist/lib/ruby', :force => true # no error
FileUtils.mv %w(junk.txt dust.txt), '/home/aamine/.trash/'
FileUtils.mv Dir.glob('test*.rb'), 'test', :noop => true, :verbose => true
Naughty way
Use the backticks approach (run any string as a command)
result = `mv "#{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file}"`
Ok, that's just a variation of calling the system command but looks much naughtier!
system("mv #{#SOURCE_DIR}/#{my_file} #{#DEST_DIR}/#{file})
should be the correct call
I recommend you to use Tanaka akira's escape library
Here is example from one my app:
cmd = Escape.shell_command(['python', Rails::Configuration.new.root_path + '/script/grab.py']).to_s
system cmd

A Ruby method for resolving relative paths while keeping absolute paths?

I am working on writing a rake build scrip which will work cross platform ( Mac OSX, Linux , Windows ). The build script will be consumed by a CI server.
I want the logic of my script to be as follows:
If the path is determined to be relative, make it absolute by making output_path = FOO_HOME + user_supplied_relative_path
If the path is determined to be absolute, take it as-is
I'm currently using Pathname.new(location).absolute? but it's not working correctly on windows.
What approach would you suggest for this?
require 'pathname'
(Pathname.new "/foo").absolute? # => true
(Pathname.new "foo").absolute? # => false
The method you're looking for is realpath.
Essentially you do this:
absolute_path = Pathname.new(path).realpath
N.B.: The Pathname module states that usage is experimental on machines that do not have unix like pathnames. So it's implementation dependent. Looks like JRuby should work on Windows.
There is a built-in function that covers both cases and does exactly what you want:
output_path = File.absolute_path(user_supplied_path, FOO_HOME)
The trick is supplying a second argument. It servers as a base directory if (and only if) the first argument is a relative path.
Pathname can do all that for you
require "pathname"
home= Pathname.new("/home/foo")
home + Pathname.new("/bin") # => #<Pathname:/bin>
home + Pathname.new("documents") # => #<Pathname:/home/foo/documents>
I am not sure about this on windows though.
You could also use File.expand_path if the relative directory is relative to the current working directory.
I checked on Linux and windows and didn't have any issues.
Assuming FOO_HOME is the working directory, the code would be:
output_path = File.expand_path user_supplied_relative_path

Resources