How to get the name of file without extension? [duplicate] - ruby

This question already has answers here:
How to get filename without extension from file path in Ruby
(10 answers)
Closed 8 years ago.
Lets say I have this string ="C:/EFI/Ulta/Filename.rb" and Im trying to split only "Filename" from it.
I tried string.split.last and it returns "Filename.rb", I tried dropping the ".rb" but drop method isnt working for me. is there any other methods I can use?

f = "C:/EFI/Ulta/Filename.rb"
File.basename(f,File.extname(f))
#=> "Filename"
How to get filename without extension from file path in Ruby

When you don't have any specific preferences about the file extension, you can use the below trick. It works with 100% confidence.
string ="C:/EFI/Ulta/Filename.rb"
File.basename(string, ".*") # => "Filename"
The only difference with djsmentya answers is, I didn't use File::extname method. At least as per OP's example, I don't see any need to use ::extname method.

path = 'C:/EFI/Ulta/Filename.rb'
def filename_from_path(path)
parts = path.split('/').last.split('.')
(parts.size > 1 ? parts[0..-2] : parts).join('.')
end
filename_from_path(path)
should do it.
Examples:
filename_from_path('C:/EFI/Ulta/Filename.rb')
# => "Filename"
filename_from_path('C:/EFI/Ulta/Filen.ame.rb')
# => "Filen.ame"
filename_from_path('C:/EFI/Ulta/Filenamerb')
# => "Filenamerb"
Although the correct way to do it is probably with File.basename as per other answers.

If you are dealing with files you can use basename
File.basename("/home/gumby/work/ruby.rb") #=> "ruby.rb"
File.basename("/home/gumby/work/ruby.rb", ".rb") #=> "ruby"
Otherwise if it's just a string:
'C:/EFI/Ulta/Filename.rb'.split('/').last.split('.').first
EDIT
If you want a generic solution working based on string manipulation only, you can use this approach:
path = 'C:\file\path\to\file.rb'
match = match = path.match(/^.*(\\|\/)(.+(\\|\/))*(.+)(\.(.+))*$/)
filename = match.values_at(match.size-2)
This will work with unix and windows path's and filename with a more than one dot.

Related

Copy a list of files from one directory to another - How to put text file into array?

Longtime lurker, first time posting! I'm new to Ruby so I would love some help on this.
I have a large text file with a list of files separated by a break, so it looks like this:
ARO_9501.jpg
ARO_9506.jpg
IMG_1499.jpg
IMG_1511.jpg
How can I get this text file into an array so I can call .each on it and copy the files to another directory?
This is how I generally do:
fileNameArray = File.read("/path/to/file.txt").split("\n")
Or, if you just need to iterate over the file names and don't necessarily need an array containing the names (it looks like you don't), I usually use this:
File.read("/path/to/file.txt").each_line do |line|
# do operations using line
end
Docs:
IO::read (File extends IO)
String .split() and each_line()
You can go this way also using IO::readlines :
ar = File.open("/home/kirti/ruby/foo.txt","r") do |fil|
fil.readlines.map(&:strip)
end
p ar
# >> ["ARO_9501.jpg", "ARO_9506.jpg", "IMG_1499.jpg", "IMG_1511.jpg"]
As per the #steenslag comments:
ar = File.readlines("/home/kirti/ruby/foo.txt").map(&:chomp)
ar # => [ "ARO_9501.jpg", "ARO_9506.jpg", "IMG_1499.jpg", "IMG_1511.jpg"]

Insert characters at end of filename (before extension)?

I have image files that I want to append a string to the name of the file, right before the extension.
Example: example.png would turn in to example-2x.png
So, I want to insert -2x right before the extension, would could be just about any image type (png, jpg, gif, etc).
If there's an easy way to do this with Ruby, great.
Rake has a nice string extension for manipulating paths:
require 'rake/pathmap'
"images/example.png".pathmap "%X-2x%x"
#=> "images/example-2x.png"
From pathmap's docs:
%X -- Everything but the file extension.
%x -- The file extension of the path. An empty string if there is no extension.
This seems to work
img[/(\.\w+)/] = "-2x#{$1}"
img1 = 'foo.png'
img1[/(\.\w+)/] = "-2x#{$1}"
img1 #=> "foo-2x.png"
img2 = 'foo.bar.jpg'
img2[/(\.\w+)/] = "-2x#{$1}"
img2 #=> "foo-2x.png.jpg"
Use basename and extname to extract the two parts you want:
http://www.ruby-doc.org/core-2.0/File.html#method-c-basename
http://www.ruby-doc.org/core-2.0/File.html#method-c-extname
def insert_before_last_dot(str, part)
idx = str.rindex('.')
return str if (idx.nil? || idx==0)
str.clone.tap { |x| x[idx] = part.to_s + '.' }
end
insert_before_last_dot('foo.jpg', '-2px') # => "foo-2px.jpg"
insert_before_last_dot('foo.bar.jpg', '-2px') # => "foo.bar-2px.jpg"
insert_before_last_dot('foo') # => "foo"
Here's what I ended up doing that seems to work pretty well across pretty much any file type.
image = 'example.png'
ext = File.extname(image)
image_2x = image.gsub(ext, "-2x"+ext)
I dont know ruby myself, but I would expect that there is some sort of string.lastIndexOf() like in java. So you basically just find the last dot, split the string around that, and then reconcatinate it with the -2x
If you're working in a Linux environment, the rename function should work.
rename {,\-2x,*}.png
In tcsh and bash shells this expands to rename .png \-2x.png *.png
> "example.png".gsub /\.[^\.]*$/, "-2x\\0"
=> "example-2x.png"
I am sure that all of the above answers are more proper than mine but i find it effective to use the replace function...
Dir | Rename-Item -NewName {$_.name -replace ".pdf"," - 2012.pdf"}
So you just take the file extension .png and replace it with -2x.png
this should work with any file extension as you are just replacing it with the same or even a different file extension and add whatever text you want before the file extension.

Ruby gsub / regex with several arguments [duplicate]

This question already has answers here:
Match a string against multiple patterns
(2 answers)
Closed 8 years ago.
I'm new to ruby and I'm trying to solve a problem.
I'm parsing through several text field where I want to remove the header which has different values. It works fine when the header always is the same:
variable = variable.gsub(/(^Header_1:$)/, '')
But when I put in several arguments it doesn't work:
variable = variable.gsub(/(^Header_1$)/ || /(^Header_2$)/ || /(^Header_3$)/ || /(^Header_4$)/ || /^:$/, '')
You can use Regexp.union:
regex = Regexp.union(
/^Header_1/,
/^Header_2/,
/^Header_3/,
/^Header_4/,
/^:$/
)
variable.gsub(regex, '')
Please note that ^something$ will not work on strings containing something more than something :)
Cause ^ is for matching beginning of string and $ is for end of string.
So i intentionally removed $.
Also you do not need brackets when you only need to remove the matched string.
You can also use it like this:
headers = %w[Header_1 Header_2 Header_3]
regex = Regexp.union(*headers.map{|s| /^#{s}/}, /^\:$/, /etc/)
variable.gsub(regex, '')
And of course you can remove headers without explicitly define them.
Most likely there are a white space after headers?
If so, you can do it as simple as:
variable = "Header_1 something else"
puts variable.gsub(/(^Header[^\s]*)?(.*)/, '\2')
#=> something else
variable = "Header_BLAH something else"
puts variable.gsub(/(^Header[^\s]*)?(.*)/, '\2')
#=> something else
Just use a proper regexp:
variable.gsub(/^(Header_1|Header_2|Header_3|Header_4|:)$/, '')
If the header is always the same format of Header_n, where n is some integer value, then you can simplify your regex greatly:
/Header_\d+/
will find every one of these:
%w[Header_1 Header_2 Header_3].grep(/Header_\d+/)
[
[0] "Header_1",
[1] "Header_2",
[2] "Header_3"
]
Tweaking it to handle finding words, not substrings:
/^Header_\d+$/
or:
/\bHeader_\d+\b/
As mentioned, using Regexp.union is a good start, but, used blindly, can result in very slow or inefficient patterns, so think ahead and help out the engine by giving it useful sub-patterns to work with:
values = %w[foo bar]
/Header_(?:\d+|#{ values.join('|') })/
=> /Header_(?:\d+|foo|bar)/
Unfortunately, Ruby doesn't have the equivalent to Perl's Regexp::Assemble module, which can build highly optimized patterns from big lists of words. Search here on Stack Overflow for examples of what it can do. For instance:
use Regexp::Assemble;
my #values = ('Header_1', 'Header_2', 'foo', 'bar', 'Header_3');
my $ra = Regexp::Assemble->new;
foreach (#values) {
$ra->add($_);
}
print $ra->re, "\n";
=> (?-xism:(?:Header_[123]|bar|foo))

Using Ruby to automate a large directory system

So I have the following little script to make a file setup for organizing reports that we get.
#This script is to create a file structure for our survey data
require 'fileutils'
f = File.open('CustomerList.txt') or die "Unable to open file..."
a = f.readlines
x = 0
while a[x] != nil
Customer = a[x]
FileUtils.mkdir_p(Customer + "/foo/bar/orders")
FileUtils.mkdir_p(Customer + "/foo/bar/employees")
FileUtils.mkdir_p(Customer + "/foo/bar/comments")
x += 1
end
Everything seems to work before the while, but I keep getting:
'mkdir': Invalid argument - Cust001_JohnJacobSmith(JJS) (Errno::EINVAL)
Which would be the first line from the CustomerList.txt. Do I need to do something to the array entry to be considered a string? Am I mismatching variable types or something?
Thanks in advance.
The following worked for me:
IO.foreach('CustomerList.txt') do |customer|
customer.chomp!
["orders", "employees", "comments"].each do |dir|
FileUtils.mkdir_p("#{customer}/foo/bar/#{dir}")
end
end
with data like so:
$ cat CustomerList.txt
Cust001_JohnJacobSmith(JJS)
Cust003_JohnJacobSmith(JJS)
Cust002_JohnJacobSmith(JJS)
A few things to make it more like the ruby way:
Use blocks when opening a file or iterating through arrays, that way you don't need to worry about closing the file or accessing the array directly.
As noted by #inger, local vars start with lower case, customer.
When you want the value of a variable in a string usign #{} is more rubinic than concatenating with +.
Also note that we took off the trailing newline using chomp! (which changes the var in place, noted by the trailing ! on the method name)

Ruby: Escaping special characters in a string

I am trying to write a method that is the same as mysqli_real_escape_string in PHP. It takes a string and escapes any 'dangerous' characters. I have looked for a method that will do this for me but I cannot find one. So I am trying to write one on my own.
This is what I have so far (I tested the pattern at Rubular.com and it worked):
# Finds the following characters and escapes them by preceding them with a backslash. Characters: ' " . * / \ -
def escape_characters_in_string(string)
pattern = %r{ (\'|\"|\.|\*|\/|\-|\\) }
string.gsub(pattern, '\\\0') # <-- Trying to take the currently found match and add a \ before it I have no idea how to do that).
end
And I am using start_string as the string I want to change, and correct_string as what I want start_string to turn into:
start_string = %("My" 'name' *is* -john- .doe. /ok?/ C:\\Drive)
correct_string = %(\"My\" \'name\' \*is\* \-john\- \.doe\. \/ok?\/ C:\\\\Drive)
Can somebody try and help me determine why I am not getting my desired output (correct_string) or tell me where I can find a method that does this, or even better tell me both? Thanks a lot!
Your pattern isn't defined correctly in your example. This is as close as I can get to your desired output.
Output
"\\\"My\\\" \\'name\\' \\*is\\* \\-john\\- \\.doe\\. \\/ok?\\/ C:\\\\Drive"
It's going to take some tweaking on your part to get it 100% but at least you can see your pattern in action now.
def self.escape_characters_in_string(string)
pattern = /(\'|\"|\.|\*|\/|\-|\\)/
string.gsub(pattern){|match|"\\" + match} # <-- Trying to take the currently found match and add a \ before it I have no idea how to do that).
end
I have changed above function like this:
def self.escape_characters_in_string(string)
pattern = /(\'|\"|\.|\*|\/|\-|\\|\)|\$|\+|\(|\^|\?|\!|\~|\`)/
string.gsub(pattern){|match|"\\" + match}
end
This is working great for regex
This should get you started:
print %("'*-.).gsub(/["'*.-]/){ |s| '\\' + s }
\"\'\*\-\.
Take a look at the ActiveRecord sanitization methods: http://api.rubyonrails.org/classes/ActiveRecord/Base.html#method-c-sanitize_sql_array
Take a look at escape_string / quote method in Mysql class here

Resources