LoginSignup
4
3

More than 5 years have passed since last update.

Rubyとmime-typesを使ってファイルの種類をフィルタリングする

Last updated at Posted at 2017-02-04

やりたい事

動画ファイルの拡張子をまとめた正規表現を作って、
その正規表現でgrepすると、動画ファイルの名前だけの配列が取得できるようにしたい。

Dir.glob('*')
# => ["hoge.mp4", "huga.png", "homu.mov"]

Dir.glob('*').grep(video_extensions_regexp)
# => ["hoge.mp4", "homu.mov"]

とりあえず、手動で拡張子を登録してみる

動画ファイルの拡張子を思いつくだけ配列に格納して、正規表現として展開する

extensions = %w(mp4 m4v avi mov)

joined_extensions = extensions.join('|')
#=> "mp4|m4v|avi|mov"

video_extensions_regexp = /\.(#{joined_extensions})$/
#=> /\.(mp4|m4v|avi|mov)$/

一応これで出来ますが、絶対漏れがありそうですよね…。
そこで、mime-typesを導入してみます。

mime-typesを使って拡張子を登録する

mime-typesには、 MIMEのタイプが網羅されているだけでなく、各タイプに該当する拡張子も登録されています。便利!

実際に試してみたい方は、gem install mime-typesして、
irbやpryなどからrequire 'mime/types'して、下記の例を実行してみてください。

mime-typesの例


MIME::Types['video/mp4']
#=> [#<MIME::Type: video/mp4>] 
# 配列が返ってくる

MIME::Types['video/mp4'].first.extensions
#=> ["mp4", "mpg4", "f4v", "f4p", "mp4v"] 
# この拡張子一覧を使う

MIME::Types[/^video/]
#=> [#<MIME::Type: video/1d-interleaved-parityfec>,
 #<MIME::Type: video/3gpp>,
 #<MIME::Type: video/3gpp-tt>,
 #<MIME::Type: video/3gpp2>,
#...
# 正規表現を渡すと、該当するMIME Typesが全部返ってくる

これを使えば、全てのvideoファイルの拡張子一覧が作れそうですね!

完成形

extensions = MIME::Types[/^video/].flat_map(&:extensions)
#=> ["3gp", "3gpp", "3g2", "3gpp2", "dl", "dv", "gl"...]

joined_extensions = extensions.join('|')
#=> "3gp|3gpp|3g2|3gpp2|dl|dv|gl..."

video_extensions_regexp = /\.(#{joined_extensions})$/
#=> /\.(3gp|3gpp|3g2|3gpp2|dl|dv|gl...)$/

といった感じで、ほとんど全ての動画ファイル形式をカバーした正規表現が作れました。

ついでに、method_missingを使って、動画以外(画像とか)にも使えるようにしたModuleを作ってみました。

複数形式に対応したModule

require 'mime/types'

module ExtReg
  def self.method_missing(name, *args)
    if instance_variable_defined?("@#{name}")
      instance_variable_get("@#{name}") # インスタンス変数に保存されていればそれを取ってくる
    elsif !(types = MIME::Types[/^#{name}/]).empty? # 該当のMIMEタイプが存在するか確認する
      extensions = types.flat_map(&:extensions)
      joined_extensions = extensions.join('|')
      extensions_regexp = /\.(#{joined_extensions})$/
      instance_variable_set("@#{name}", extensions_regexp) # @videoなどに保存しておく
      extensions_regexp
    else
      super
    end
  end
end

ExtReg.video
#=> /\.(3gp|3gpp|3g2|3gpp2|dl|dv|...)$/

ExtReg.image
#=> /\.(bmp|cgm|g3|gif|ief|jp2|...)$/

これを使うと、頭の例がこうなります。

Dir.glob('*')
# => ["hoge.mp4", "huga.png", "homu.mov"]

Dir.glob('*').grep(ExtReg.video)
# => ["hoge.mp4", "homu.mov"]

簡単に目的達成できました!
これでもう、拡張子を自力で列挙しなくて済む…。

4
3
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3