Determine file type in Ruby

Viewed 53658

How does one reliably determine a file's type? File extension analysis is not acceptable. There must be a rubyesque tool similar to the UNIX file(1) command?

This is regarding MIME or content type, not file system classifications, such as directory, file, or socket.

13 Answers

There is a ruby binding to libmagic that does what you need. It is available as a gem named ruby-filemagic:

gem install ruby-filemagic

Require libmagic-dev.

The documentation seems a little thin, but this should get you started:

$ irb 
irb(main):001:0> require 'filemagic' 
=> true
irb(main):002:0> fm = FileMagic.new
=> #<FileMagic:0x7fd4afb0>
irb(main):003:0> fm.file('foo.zip') 
=> "Zip archive data, at least v2.0 to extract"
irb(main):004:0> 

If you're on a Unix machine try this:

mimetype = `file -Ib #{path}`.gsub(/\n/,"")

I'm not aware of any pure Ruby solutions that work as reliably as 'file'.

Edited to add: depending what OS you are running you may need to use 'i' instead of 'I' to get file to return a mime-type.

This was added as a comment on this answer but should really be its own answer:

path = # path to your file

IO.popen(
  ["file", "--brief", "--mime-type", path],
  in: :close, err: :close
) { |io| io.read.chomp }

I can confirm that it worked for me.

For those who came here by the search engine, a modern approach to find the MimeType in pure ruby is to use the mimemagic gem.

require 'mimemagic'

MimeMagic.by_magic(File.open('tux.jpg')).type # => "image/jpeg" 

If you feel that is safe to use only the file extension, then you can use the mime-types gem:

MIME::Types.type_for('tux.jpg') => [#<MIME::Type: image/jpeg>]

You could give shared-mime a try (gem install shared-mime-info). Requires the use ofthe Freedesktop shared-mime-info library, but does both filename/extension checks as well as "magic" checks... tried giving it a whirl myself just now but I don't have the freedesktop shared-mime-info database installed and have to do "real work," unfortunately, but it might be what you're looking for.

You could give a go with MIME::Types for Ruby.

This library allows for the identification of a file’s likely MIME content type. The identification of MIME content type is based on a file’s filename extensions.

Related