Reputation: 5454
I have been trying to work out a file rename program based on ruby, as a programming exercise for myself (I am aware of rename under linux, but I want to learn Ruby, and rename is not available in Mac).
From the code below, the issue is that the .include?
method always returns false even though I see the filename contains such search pattern. If I comment out the include?
check, gsub()
does not seem to generate a new file name at all (i.e. file name remains the same). So can someone please take a look at see what I did wrong? Thanks a bunch in advance!
Here is the expected behavior: Assuming that in current folder there are three files: a1.jpg, a2.jpg, and a3.jpg The Ruby script should be able to rename it to b1.jpg, b2.jpg, b3.jpg
#!/Users/Antony/.rvm/rubies/ruby-1.9.3-p194/bin/ruby
puts "Enter the file search query"
searchPattern = gets
puts "Enter the target to replace"
target = gets
puts "Enter the new target name"
newTarget = gets
Dir.glob("./*").sort.each do |entry|
origin = File.basename(entry, File.extname(entry))
if origin.include?(searchPattern)
newEntry = origin.gsub(target, newTarget)
File.rename( origin, newEntry )
puts "Rename from " + origin + " to " + newEntry
end
end
Upvotes: 12
Views: 11694
Reputation: 468
In a folder, I wanted to remove the trailing underscore _
of any audio filename while keeping everything else. Sharing my code here as it might help someone.
What the program does:
c:/your/path/here
(make sure to use slashes /
, not backslashes, \
, and without the final one).mp3
(without the dot .
)_
c:/your/path/here/filename_.mp3
and renames it c:/your/path/here/filename.mp3
while keeping the file’s original extension.
puts 'Enter directory path'
path = gets.strip
directory_path = Dir.glob("#{path}/*")
# Get file extension
puts 'Enter file extension'
file_extension = gets.strip
# Get trailing characters to remove
puts 'Enter trailing characters to remove'
trailing_characters = gets.strip
suffix = "#{trailing_characters}.#{file_extension}"
# Rename file if condition is met
directory_path.each do |file_path|
next unless file_path.end_with?(suffix)
File.rename(file_path, "#{file_path.delete_suffix(suffix)}.#{file_extension}")
end
Upvotes: 0
Reputation: 21
I made a small script to rename the entire DBZ serie by seasons and implement this:
count = 1
new_name = "Dragon Ball Z S05E"
format_file = ".mkv"
Dir.glob("dragon ball Z*").each do |old_name|
File.rename(old_name, new_name + count.to_s + format_file)
count += 1
end
The result would be: Dragon Ball Z S05E1 Dragon Ball Z S05E2 Dragon Ball Z S05E3
Upvotes: 1
Reputation: 926
Here's a short version I've used today (without pattern matching)
Save this as rename.rb file and run it inside the command prompt with ruby rename.rb
count = 1
newname = "car"
Dir["/path/to/folder/*"].each do |old|
File.rename(old, newname + count.to_s)
count += 1
end
I had /Copy of _MG_2435.JPG converted into car1, car2, ...
Upvotes: 2
Reputation: 1687
I used the accepted answer to fix a bunch of copied files' names.
Dir.glob('./*').sort.each do |entry|
if File.basename(entry).include?(' copy')
newEntry = entry.gsub(' copy', '')
File.rename( entry, newEntry )
end
end
Upvotes: 4
Reputation: 45057
Slightly modified version:
puts "Enter the file search query"
searchPattern = gets.strip
puts "Enter the target to replace"
target = gets.strip
puts "Enter the new target name"
newTarget = gets.strip
Dir.glob(searchPattern).sort.each do |entry|
if File.basename(entry, File.extname(entry)).include?(target)
newEntry = entry.gsub(target, newTarget)
File.rename( entry, newEntry )
puts "Rename from " + entry + " to " + newEntry
end
end
Key differences:
.strip
to remove the trailing newline that you get from gets
. Otherwise, this newline character will mess up all of your match attempts.glob
call instead of globbing for everything and then manually filtering it later.entry
(that is, the complete filename) in the calls to gsub
and rename
instead of origin
. origin
is really only useful for the .include?
test. Since it's a fragment of a filename, it can't be used with rename
. I removed the origin
variable entirely to avoid the temptation to misuse it.For your example folder structure, entering *.jpg
, a
, and b
for the three input prompts (respectively) should rename the files as you are expecting.
Upvotes: 12
Reputation: 303244
Your problem is that gets
returns a newline at the end of the string. So, if you type "foo" then searchPattern
becomes "foo\n"
. The simplest fix is:
searchPattern = gets.chomp
I might rewrite your code slightly:
$stdout.sync
print "Enter the file search query: "; search = gets.chomp
print "Enter the target to replace: "; target = gets.chomp
print " Enter the new target name: "; replace = gets.chomp
Dir['*'].each do |file|
# Skip directories
next unless File.file?(file)
old_name = File.basename(file,'.*')
if old_name.include?(search)
# Are you sure you want gsub here, and not sub?
# Don't use `old_name` here, it doesn't have the extension
new_name = File.basename(file).gsub(target,replace)
File.rename( file, new_path )
puts "Renamed #{file} to #{new_name}" if $DEBUG
end
end
Upvotes: 3