如何在ruby中批量重命名文件

时间:2022-04-15 10:36:18

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 from gets. 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 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.
  • 在对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 from gets. 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 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.
  • 在对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,...