I'm moving my notes to evernote. To this end I need to convert .doc/.docx files to rtf. The reason for this is that I have a script to import rtf into evernote. However, some of my .doc/.docx files contain images.

Is there any way to identify which .doc/.docx files contain images without viewing them all? I have thousands. This way I can simply open the few that have images and copy/paste the entire content straight into evernote.

Should say that I'm using OS X 10.6.8.


Where do .doc files store images?

Word doc files are actually zipped and then put into a container format. They store media somewhere in this compiled file format, probably right after the doc format's header. After the image data, there's your real document as a zip-compatible folder.

file layout

So when you try to unzip a doc file, you get an excess number of bytes at the beginning. These are your images (plus the format header). You could now attempt to unzip the file and check the excess amount of bytes.

charon:test werner$ unzip -c images.doc > /dev/null
warning [images.doc]:  47166 extra bytes at beginning or within zipfile

charon:test werner$ unzip -c noimages.doc > /dev/null
warning [noimages2.doc]:  6060 extra bytes at beginning or within zipfile

Through testing, I found the header of "plaintext" Word documents to be 6060 bytes large (some are a bit larger though). We can try to exploit it for determining whether there's an image inside a document. Let's just say 8000 bytes — since real images will definitely have more than a few KB.

What about .docx files?

With the Office 2007 format (docx), this is much easier. These are actual zipped files, and any Word file that contains embedded media of any kind (images, video) will include the file.docx/word/media directory. So, we just need to unzip the docx files and check if that directory exists.

A script to check for images

  • Create a new empty file, call it docx-images.rb, and paste the following content:

    #!/usr/bin/env ruby
    require 'open3'
    TEMPDIR = "/tmp/word/"
    # check for docx files
    Dir.glob("**/*.docx").each do |file|
      system("rm -rf '#{TEMPDIR}'")
      system("unzip '#{file}' -d #{TEMPDIR} > /dev/null")
      if File.directory?("#{TEMPDIR}/word/media/")
        puts file
    # check for doc files
    Dir.glob("**/*.doc").each do |file|
      stdin, stdout, stderr = Open3.popen3("unzip -c '#{file}' > /dev/null")
      info = stderr.readlines[0]
      info = info.gsub(" extra bytes at beginning or within zipfile", "").gsub(/warning\s\[.*\]:\s+/, "")
      if info.to_i > 8000 # assume a little more than usual header size
        puts file
  • Save it somewhere, preferably in a folder where you want to begin your search for docx files from, maybe your Documents folder.

  • Now, open up Terminal.app, and use cd ~/Documents to go there.

  • Type ruby docx-images.rb, and it will recursively scan your Documents folder for docx and doc files. It'll unzip the former to /tmp/word, and check if they contain embedded media. The latter are just unzipped to /dev/null, thus leaving no traces behind.

  • You'll end up with a list of those with embedded media.


To prove that this works, I created four files. One with images, one without images – both as doc and docx:


Then, running the script:

charon:test werner$ ruby docx-images.rb 

Clearly, the script could be improved to check for actual images in that media folder, but it's unlikely it exists unless the file really contains any media. The same goes for the "6060" bytes check. It's a hack, but it works for me.

Of course, the script depends on the implementation of unzip on the respective system, but it works for the OS X version.

  • many thanks for the reply. I copied the code into a new document into one of my folders that contained .doc files and sub folders with .doc files in. I then use the terminal to navigate to the folder and run the ruby code. The terminal window then listed a number of .doc files. Would I be right in assuming that this list should contain those .doc files that contain images? If this is the case then something is not quite right as I got a complete list of the files in the folders and sub folders. I should add that some .doc files will be in 97 format. – rev Apr 15 '12 at 14:33
  • So you got a list of every .doc file instead of just those with the images? Can you run unzip -c some-file.doc > /dev/null for one of these files that were misclassified and tell me if there's another offset than 6060 bytes? – slhck Apr 15 '12 at 14:51
  • Simons-MacBook-Pro:7000-Acts and the Early church Simon$ unzip -c 7000-TROAS.doc > /dev/null End-of-central-directory signature not found. Either this file is not a zipfile, or it constitutes one disk of a multi-part archive. In the latter case the central directory and zipfile comment will be found on the last disk(s) of this archive. note: 7000-TROAS.doc may be a plain executable, not an archive unzip: cannot find zipfile directory in one of 7000-TROAS.doc or 7000-TROAS.doc.zip, and cannot find 7000-TROAS.doc.ZIP, period. – rev Apr 15 '12 at 15:08
  • Hm, that makes me believe these files weren't created with the same version of Word that I have (in that case, 2011) — but "Word 97-2003" is one kind of file format that should be the same regardless of the type. Of course my script will fail since it assumes the 6060 bytes header for all files without images. Maybe you can supply an example of a document that has images, and one that doesn't? – slhck Apr 15 '12 at 15:44
  • How do I send them to you? – rev Apr 15 '12 at 16:00

For Windows:

  • Renaming the .docx to .zip, opening the zip file and extracting the images (Best way!).
  • Then look for the image under \zipfile\word\media for the image.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.