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).
我一直试图找出一个基于ruby的文件重命名程序,作为我自己的编程练习(我知道在linux下重命名,但我想学习Ruby,并且在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!
从下面的代码,问题是.include?即使我看到文件名包含这样的搜索模式,方法总是返回false。如果我评论出包含?检查,gsub()似乎根本不生成新的文件名(即文件名保持不变)。所以有人可以看看我做错了什么?先谢谢了!
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
这是预期的行为:假设在当前文件夹中有三个文件:a1.jpg,a2.jpg和a3.jpg Ruby脚本应该能够将其重命名为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
4 个解决方案
#1
10
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:
主要差异:
- Use
.strip
to remove the trailing newline that you get fromgets
. Otherwise, this newline character will mess up all of your match attempts. - 使用.strip删除从get获得的尾随换行符。否则,此换行符将使您的所有匹配尝试陷入混乱。
- Use the user-provided search pattern in the
glob
call instead of globbing for everything and then manually filtering it later. - 在glob调用中使用用户提供的搜索模式,而不是为所有内容进行通配,然后在以后手动过滤它。
- Use
entry
(that is, the complete filename) in the calls togsub
andrename
instead oforigin
.origin
is really only useful for the.include?
test. Since it's a fragment of a filename, it can't be used withrename
. I removed theorigin
variable entirely to avoid the temptation to misuse it. - 在对gsub的调用中使用entry(即完整的文件名)并重命名而不是origin。 origin真的只对.include有用吗?测试。由于它是文件名的片段,因此不能与重命名一起使用。我完全删除了原始变量,以避免滥用它的诱惑。
For your example folder structure, entering *.jpg
, a
, and b
for the three input prompts (respectively) should rename the files as you are expecting.
对于示例文件夹结构,为三个输入提示(分别)输入* .jpg,a和b应该按照您的预期重命名文件。
#2
3
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
#3
2
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:
你的问题是gets返回字符串末尾的换行符。所以,如果输入“foo”,则searchPattern变为“foo \ n”。最简单的解决方法是:
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
#4
1
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
将其保存为rename.rb文件,并使用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, ...
我有_MG_2435.JPG的副本转换成car1,car2,...
#1
10
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:
主要差异:
- Use
.strip
to remove the trailing newline that you get fromgets
. Otherwise, this newline character will mess up all of your match attempts. - 使用.strip删除从get获得的尾随换行符。否则,此换行符将使您的所有匹配尝试陷入混乱。
- Use the user-provided search pattern in the
glob
call instead of globbing for everything and then manually filtering it later. - 在glob调用中使用用户提供的搜索模式,而不是为所有内容进行通配,然后在以后手动过滤它。
- Use
entry
(that is, the complete filename) in the calls togsub
andrename
instead oforigin
.origin
is really only useful for the.include?
test. Since it's a fragment of a filename, it can't be used withrename
. I removed theorigin
variable entirely to avoid the temptation to misuse it. - 在对gsub的调用中使用entry(即完整的文件名)并重命名而不是origin。 origin真的只对.include有用吗?测试。由于它是文件名的片段,因此不能与重命名一起使用。我完全删除了原始变量,以避免滥用它的诱惑。
For your example folder structure, entering *.jpg
, a
, and b
for the three input prompts (respectively) should rename the files as you are expecting.
对于示例文件夹结构,为三个输入提示(分别)输入* .jpg,a和b应该按照您的预期重命名文件。
#2
3
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
#3
2
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:
你的问题是gets返回字符串末尾的换行符。所以,如果输入“foo”,则searchPattern变为“foo \ n”。最简单的解决方法是:
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
#4
1
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
将其保存为rename.rb文件,并使用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, ...
我有_MG_2435.JPG的副本转换成car1,car2,...