Help us understand the problem. What is going on with this article?

Rubyのスクリプトでファイル名一括置換

More than 3 years have passed since last update.

2016.1.29
scivolaさまにご指摘を受け、一部コードを修正しました。ありがとうございます。

はじめに

初心者向けです。

Rubyに少しは触ってみたい…と漠然と思っていたのですが、
ファイル名を一括でいじりたいなーという機会があり、勉強がてらスクリプトを書いてみました。
(普通にシェルでやれとかリネームツール使えとかいう話ですが…)

指定拡張子のファイルを連番にしたい

同じ種類のファイルを連番にしたいなーというとき用。

rename_target_extension.rb
# 指定拡張子のファイル名を連番にしたい

require 'fileutils'

target = ARGV[0]
prefix = ARGV[1]

if target.nil?
   print "対象とする拡張子を入力してください\n"
   exit
end

Dir.glob("*.#{target}").each_with_index do |filename, index|
  newname = filename.gsub(/.+(?=\.[^.]+$)/) { sprintf("%s%03d", prefix, index) }
  print "#{filename} -> #{newname}\n"
  FileUtils.mv(filename, newname)
end

実行してみる

リネームしたいフォルダで実行するとこんな感じになります。

$ ruby rename_target_extension.rb png hoge
aaa.png -> hoge000.png
bbb.png -> hoge001.png

ファイル名内の指定文字列を置換したい

上で連番にしたようなファイル郡があるときに、一括でファイル名を変更する用。

rename_target_string.rb
# ファイル名の一部をまとめて置換したい

require 'fileutils'

target = ARGV[0]
conv = ARGV[1]

if target.nil?
  print "対象文字列が空です\n"
  exit
end

Dir.glob("*") do |filename|
  newname = filename.gsub(/#{target}/, "#{conv}")
  if newname != filename
     print "#{filename} -> #{newname}\n"
     FileUtils.mv(filename, newname)
  end
end

実行してみる

リネームしたいフォルダで実行するとこんな感じになります。

$ ruby ../../rb_script/rename_target.rb ho sa
hoge000.png -> sage000.png
hoge001.png -> sage001.png

できました\('ω')/

詳解メモ

ここからは自分用のメモみたいなものです。

ライブラリのロード

require 'fileutils'

fileutilsをロードすることで、ファイル操作を行えるようになります。

コマンドライン引数の取得

target = ARGV[0]
prefix = ARGV[1]

コマンド実行時の引数はARGV[]で取得します。
さらに複数ある場合はARGV[2], ARGV[3]..と入ってきます。
因みに、ruby実行時のファイル名自体を取得したい場合、$0で取得できます。
(上記実行例であれば$0で "rename_target_extension.rb" が取得できる)

変数の展開

文字列中に式の結果や変数の中身を使いたい場合は、#{}でくくります。

Dir.glob("*.#{target}")

フォルダ内のファイル取得

Dir.glob("*.#{target}") do |filename|

Dir.glob()の引数にマッチするファイルを、カレントディレクトリから取得します。
例えばDir.glob("*")などとすれば全てのファイルが対象になります。

Dir.globだけですと配列を返しますが、
例のように Dir.glob(..) do |filename| .. end としたり、
Dir.glob { |filename| .. } とすることで、取得した各ファイル名に対する処理を行うことができます。

文字列の置換

filename.gsub(/#{target}/, "#{conv}")
filename.gsub(/.+(?=\.[^.]+$)/) { sprintf("%s%03d", ARGV[1], index) }

文字列に対し、gsubを使えば置換が行えます。
正規表現で置換対象を抜き出すこともできます。
複雑な式などはブロック形式(filename.gsub(..){ .. })の方が見やすくて良さそうですね。

拡張子以外の文字列の抽出

(/.+(?=\.[^.]+$)/)

拡張子を除く部分を抽出する正規表現です。
ざっくり説明すると、.+で文字列全体を指定し、
そこから(?=\.[^.]+$)で拡張子部分を排除しています。

\.[^.]+$がカンマから始まってカンマ以外の文字が続いたのち文字列の最後尾に達する部分を示し、
?=がその否定を表しています。

(´-`)oO(正規表現ちゃんと勉強しないとなあ…)

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away