How to write file path in elixir-iex? I am using windows - windows

I wrote this:
File.read("C:\Users\Mostafiz\OneDrive\Desktop\New_Text_Document")
But getting the following error:
{:error, :enoent}
I copied this file path from the properties that file.
C:\Users\Mostafiz\OneDrive\Desktop
Now my question is, how to write this file path in elixir-iex?

Elixir, like many other languages, interprets backspaces inside strings as escapes. Some of them have special meanings (like \n for a newline), but the ones that don't become the escaped character itself. So for example, \U becomes U. You can check this by writing IO.puts <your string> in iex, and you'll see that your backslashes disappear:
iex(1)> IO.puts "C:\Users\Mostafiz\OneDrive\Desktop\New_Text_Document"
C:UsersMostafizOneDriveDesktopNew_Text_Document
To get the path you want you need to either escape the backspash itself (writing \\ in your string) or use forward slashes, since they are also recognized as path separators.
So either this:
iex(1)> IO.puts "C:\\Users\\Mostafiz\\OneDrive\\Desktop\\New_Text_Document"
C:\Users\Mostafiz\OneDrive\Desktop\New_Text_Document
Or this:
iex(1)> IO.puts "C:/Users/Mostafiz/OneDrive/Desktop/New_Text_Document"
C:/Users/Mostafiz/OneDrive/Desktop/New_Text_Document

Always use ~S sigil for paths, it prevents string interpolation.
iex|💧|1 ▸ "C:\Users\Mostafiz\OneDrive\Desktop\New_Text_Document"
"C:UsersMostafizOneDriveDesktopNew_Text_Document"
iex|💧|2 ▸ ~S"C:\Users\Mostafiz\OneDrive\Desktop\New_Text_Document"
"C:\\Users\\Mostafiz\\OneDrive\\Desktop\\New_Text_Document"

It may be because you need to escape the forward slashes.
Does File.read("C:\\Users\\Mostafiz\\OneDrive\\Desktop\\New_Text_Document") work?

Related

Use Dir.chdir to work with a path name with spaces in it

On Mac OSX, using the Ruby Dir class, I want to change to a directory that has spaces in it. I have tried:
Dir.chdir('/Users/Chris/Library/Application\ Support')
but received the exception
Errno::ENOENT: No such file or directory
How do I do this?
Don't Escape Spaces Inside Single Quotes
Don't escape spaces inside single quotes. If you do, the String will contain a literal quote character, which will not match your directory name. Consider:
'\ '
#=> "\\ "
If you have a space in the name, just use proper quoting without escapes for the spaces. Examples include:
Dir.chdir '/Users/Chris/Library/Application Support'
Dir.chdir "/Users/Chris/Library/Application Support"
Dir.chdir %q(/Users/Chris/Library/Application Support)
There may be situations where you need escapes inside single quotes (such as escaping a single-quote character, e.g. '\'') but your example is not one of them.

How to obtain basename in ruby from the given file path in unix or windows format?

I need to parse a basename in ruby a from file path which I get as input. Unix format works fine on Linux.
File.basename("/tmp/text.txt")
return "text.txt".
However, when I get input in windows format:
File.basename("C:\Users\john\note.txt")
or
File.basename("C:\\Users\\john\\note.txt")
"C:Usersjohn\note.txt" is the output (note that \n is a new line there), but I didn't get "note.txt".
Is there some nice solution in ruby/rails?
Solution:
"C:\\test\\note.txt".split(/\\|\//).last
=> "note.txt"
"/tmp/test/note.txt".split(/\\|\//).last
=> "note.txt"
If the Linux file name doesn't contain \, it will work.
Try pathname:
require 'pathname'
Pathname.new('C:\Users\john\note.txt').basename
# => #<Pathname:note.txt>
Pathname docs
Ref How to get filename without extension from file path in Ruby
I'm not convinced that you have a problem with your code. I think you have a problem with your test.
Ruby also uses the backslash character for escape sequences in strings, so when you type the String literal "C:\Users\john\note.txt", Ruby sees the first two backslashes as invalid escape sequences, and so ignores the escape character. \n refers to a newline. So, to Ruby, this literal is the same as "C:Usersjohn\note.txt". There aren't any file separators in that sequence, since \n is a newline, not a backslash followed by the letter n, so File.basename just returns it as it receives it.
If you ask for user input in either a graphical user interface (GUI) or command line interface (CLI), the user entering input needn't worry about Ruby String escape sequences; those only matter for String literals directly in the code. Try it! Type gets into IRB or Pry, and type or copy a file path, and press Enter, and see how Ruby displays it as a String literal.
On Windows, Ruby accepts paths given using both "/" (File::SEPARATOR) and "\\" (File::ALT_SEPARATOR), so you don't need to worry about conversion unless you are displaying it to the user.
Backslashes, while how Windows expresses things, are just a giant nuisance. Within a double-quoted string they have special meaning so you either need to do:
File.basename("C:\\Users\\john\\note.txt")
Or use single quotes that avoid the issue:
File.basename('C:\Users\john\note.txt')
Or use regular slashes which aren't impacted:
File.basename("C:/Users/john/note.txt")
Where Ruby does the mapping for you to the platform-specific path separator.

Absolute path in perl's copy command gone wrong?

This is my very simple code, which isn't working, for some reason I can't figure out.
#!/usr/bin/perl
use File::Copy;
$old = "car_lexusisf_gray_30inclination_000azimuth.png";
$new = "C:\Users\Lenovo\Documents\mycomp\simulation\cars\zzzorganizedbyviews\00inclination_000azimuth\lexuscopy.png";
copy ($old, $new) or die "File cannot be copied.";
I get the error that the file can't be copied.
I know there's nothing wrong with the copy command because if I set the value of $new to something simple without a path, it works. But what is wrong in the representation of the path as I've written it above? If I copy and past it into the address bar of windows explorer, it reaches that folder fine.
Tip: print out the paths before you perform the copy. You'll see this:
C:SERSenovodocumentsmycompsimulationrszzzorganizedbyviewsinclination_000azimuthexuscopy.png
Not what we wanted. The backslash is an escape character in Perl, which needs to be escaped itself. If the backslash sequence does not form a valid escape, then it's silently ignored. With escaped backslashes, your string would look like:
"C:\\Users\\Lenovo\\Documents\\mycomp\\simulation\\cars\\zzzorganizedbyviews\\00inclination_000azimuth\\lexuscopy.png";
or just use forward slashes instead – in most cases, Unix-style paths work fine on Windows too.
Here is a list of escapes you accidentally used:
\U uppercases the rest
\L lowercases the rest
\ca is a control character (ASCII 1, the start of heading)
\00 is an octal character, here the NUL byte
\l lowercases the next character.
If no interpolation is intended, use single quotes instead of double quotes.

Take in escaped input in Ruby command line app

I'm writing a Ruby command line application in which the user has to enter a "format string" (much like Date.strptime/strftime's strings).
I tried taking them in as arguments to the command, eg
> torque "%A\n%d\n%i, %u"
but it seems that bash actually removes all backslashes from input before it can be processed (plus a lot of trouble with spaces). I also tried the highline gem, which has some more advanced input options, but that automatically escapes backslashes "\" -> "\\" and provides no alternate options.
My current solution is to do a find-and-replace: "\\n" -> "\n". This would take care of the problem, but it also seems hacky and awful.
I could have users write the string in a text file (complicated for the user) or treat some other character, like "&&", as a newline (still complicated for the user).
What is the best way for users to input escaped characters on the command line?
(UPDATE: I checked the documentation for strptime/strftime, and the format strings for those functions replace newline characters with "%n", tabs with "%t", etc. So for now I'm doing that, but any other suggestions are welcome)
What you're looking for is using single quotes instead of double quotes.
Thus:
> torque '%A\n%d\n%i, %u'
Any string quoted in single quotes 'eg.' is does not go through any expansions and is used as is.
More details can be found in the Quoting section of man bash.
From man bash:
Enclosing characters in single quotes preserves the literal value of each character within the quotes. A single quote may not occur between single quotes, even when preceded by a backslash.
p eval("\"#{gets.chomp}\"")
Example use:
\n\b # Input by the user from the keyboard
"\n\b" # Value from the script
%A\n%d\n%i, %u # Input by the user from the keyboard
"%A\n%d\n%i, %u" # Value from the script

Single quote string interpolation to access a file in linux

How do I make the parameter file of the method sound become the file name of the .fifo >extension using single quotes? I've searched up and down, and tried many different >approaches, but I think I need a new set of eyes on this one.
def sound(file)
#cli.stream_audio('audio\file.fifo')
end
Alright so I finally got it working, might not be the correct way but this seemed to do the trick. First thing, there may have been some white space interfering with my file parameter. Then I used the File.join option that I saw posted here by a few different people.
I used a bit of each of the answers really, and this is how it came out:
def sound(file)
file = file.strip
file = File.join('audio/',"#{file}.fifo")
#cli.stream_audio(file) if File.exist? file
end
Works like a charm! :D
Ruby interpolation requires that you use double quotes.
Is there a reason you need to use single quotes?
def sound(FILE)
#cli.stream_audio("audio/#{FILE}.fifo")
end
As Charles Caldwell stated in his comment, the best way to get cross-platform file paths to work correctly would be to use File.join. Using that, your method would look like this:
def sound(FILE)
#cli.stream_audio(File.join("audio", "#{FILE}.fifo"))
end
Your problem is with your usage of file path separators. You are using a \. Whereas this may not seem like a big deal, it actually is when used in Ruby strings.
When you use \ in a single quoted string, nothing happens. It is evaluated as-is:
puts 'Hello\tWorld' #=> Hello\tWorld
Notice what happens when we use double quotes:
puts "Hello\tWorld" #=> "Hello World"
The \t got interpreted as a tab. That's because, much like how Ruby will interpolate #{} code in a double quote, it will also interpret \n or \t into a new line or tab. So when it sees "audio\file.fifo" it is actually seeing "audio" with a \f and "ile.fifo". It then determines that \f means 'form feed' and adds it to your string. Here is a list of escape sequences. It is for C++ but it works across most languages.
As #sawa pointed out, if your escape sequence does not exist (for instance \y) then it will just remove the \ and leave the 'y'.
"audio\yourfile.fifo" #=> audioyourfile.fifo
There are three possible solutions:
Use a forward slash:
"audio/#{file}.fifo"
The forward slash will be interpreted as a file path separator when passed to the system. I do most my work on Windows which uses \ but using / in my code is perfectly fine.
Use \\:
"audio\\#{file}.fifo"
Using a double \\ escapes the \ and causes it to be read as you intended it.
Use File.join:
File.join("audio", "#{file}.fifo")
This will output the parameters with whatever file separator is setup as in the File::SEPARATOR constant.

Resources