I shoot RAW+JPG, namely NEF and JPG. After viewing sometimes hundreds of images (using a simple program) and deleting the JPGs, I have many unnecessary leftover NEF files. If there was a script to delete any orphan NEF files in the directory, that would be very helpful. I read a similar question here "How to delete JPG files, but only if the matching RAW file exists?" and the solution presented with the Command Prompt works very well. I was wondering if one was available for my predicament?

  • \$\begingroup\$ Can you provide a link to that question here? The answer to this will almost certainly be a shell script - maybe ask on SuperUser instead, because if you have a good definition of what you need to delete (by filename), this is a fairly trivial task. \$\endgroup\$ Commented Apr 10, 2012 at 11:19
  • 1
    \$\begingroup\$ For the future, just use Geeqie. It deletes the matching RAW files automatically and any other which is defined as a 'sidecar' file based on the config. \$\endgroup\$
    – Itai
    Commented Apr 12, 2012 at 0:44
  • \$\begingroup\$ I have my setup as follows: NEF: \\Photos\RAW\YYYY\YYYY-MM-DD\original.nef Jpegs: \\Photos\RAW\YYYY\YYYY-MM-DD\original.jpeg Anyway I can apply this script to this? \$\endgroup\$
    – user14216
    Commented Dec 24, 2012 at 19:33
  • \$\begingroup\$ In Bash: orphan=.nef; parent=.jpeg; for f in *"$orphan"; do F="${f%$orphan}$parent"; if test ! -f "$F"; then echo "Identified orphan: $f exists but not $F"; fi done Can't belief how long and complicated those other answers are. Yeah, I know, answering in comment, but it's protected... \$\endgroup\$
    – Nobody
    Commented Nov 1, 2018 at 0:12

3 Answers 3


I wrote a script in Python to do the work for me. It's called remove-orphaned-raw-images.py and I published it on Github.

Basically it iterates over all the files in a given folder and moves orphaned raw images (in my case *.CR2 files with no matching JPEG) to a backup folder. Optionally you can tell the script to actually delete the files.

Here is an outline of the algorithm:

  • Get a list of all the files in the selected directory.
  • Sort those files into RAW and JPEG files (append them to separate lists).
  • Check for each item in the RAW images list that a match exists in the JPEG list;
    if not, append this image to a list of orphaned raw images.
  • Move the images in the list of orphaned images to a backup folder
    (or directly delete them if explicitly wanted).

The tool will tell you how to use it when run with the help option -h on the command line.

This problem also occured to me, which is why I wrote this tool. I'm using my DSLR to take JPEG or RAW+JPEG images, never only RAW. When sorting out blurry or otherwise bad shots, I use the JPEGs to quickly take a look at them and delete the bad ones. This leaves me with left over RAW images of which I deleted the matching JPEGs (for a reason).


Using the question you mentioned - I have written you a script

ok warning! be careful with this script! - MAKE A BACKUP

1) Make a bat file called clean.bat and put it in the dir that you want to work with

2) Then enter the following into the bat file

mkdir keep
for /f "delims==" %%r in ('dir /b *.jpg') do move "%%~dpr%%~nr.nef" "%CD%\keep\" 2> nul
move *.jpg "%CD%\keep\"
del *.nef
del *.jpg
move "%CD%\keep\*.*" "%CD%\"
rmdir keep

3) Open the command prompt as admin and navigate to the folder with the clean.bat 4) run clean.bat

Basically the flow of the script is

  • Make a directory called Keep
  • Move all matching NEF files to the keep folder
  • Move all Jpegs to the keep folder
  • Then delete all the files from source folder
  • Move the keep files back
  • Remove the keep folder

Please, PLEASE test this out!

UPDATE: Made script change to work with folders that have spaces in them

  • 2
    \$\begingroup\$ +1 for a straightforward, one shot solution! I've been needing this solution for long time. I used to elaborate commands by pasting DIR output into excel, and using complicated operators like vlookup to generate individual commands, but this catches almost all my needs. Tested the script and its completely fine for me. Had to consult several references to fully understand the script and be able to modify it for other similar operations. \$\endgroup\$
    – Jahaziel
    Commented Apr 11, 2012 at 16:25
  • \$\begingroup\$ Fantastic, you have saved me hours of tedious work!!! I tried it several times and it works too fast. It is just what I was looking for. \$\endgroup\$
    – Al H
    Commented Apr 12, 2012 at 2:24
  • \$\begingroup\$ @al-h - please can you tick as correct then? thanks \$\endgroup\$
    – Rob
    Commented Apr 12, 2012 at 6:09
  • \$\begingroup\$ Rob I am unsure what you mean by "please can you tick as correct" I don't see somewhere I can check a correct link. \$\endgroup\$
    – Al H
    Commented Apr 27, 2012 at 2:29
  • \$\begingroup\$ One thing I did notice. This does not work on folders on the desktop (deletes all jpg & NEF files), so test first. I am running Windows XP Pro. \$\endgroup\$
    – Al H
    Commented Apr 27, 2012 at 2:47

Here's my python script to delete cr2's w/o a jpeg.

It searches recursively within the current directory, ".". It considers all images in all folders.

import os 
import sys

#Searches through the current directory, recursively, looking for any raw
#and jpeg files. It enumerates the jpegs it finds, without the extension, and
#then enumerates the raw files it finds. If it finds a raw file for which no
#jpeg exists, then it deletes the raw file.
# This WILL NOT WORK, if there are files with repeated file numbers.
# this will NOT be an issue if there's only one camera. 

# A dict of filename: (rawpath, jpegpath)
files_seen = {}

for (cur_dir, subdirs, files) in os.walk("."):
  for file in files:
    fname, fext = os.path.splitext(file)
    fext = fext.lower()

    if (fext == ".jpg"):
      content = files_seen.setdefault(fname, [None, None])
      # if it is then filenames have du'ped
      assert(content[1] is None)
      content[1] = os.path.join(cur_dir, file)

    elif (fext == ".cr2"):
      content = files_seen.setdefault(fname, [None, None])
      assert(content[0] is None)
      content[0] = os.path.join(cur_dir, file)

#at the end, we look for raw files without a jpeg,

for key in files_seen:
  (raw_path, jpeg_path) = files_seen[key]

  if jpeg_path is None:
    print("Deleting: %s" % raw_path)

  • \$\begingroup\$ Just rename ".cr2" to ".nef" \$\endgroup\$
    – Peter pete
    Commented Mar 10, 2013 at 21:06
  • \$\begingroup\$ I'm not familiar with Python, but I see it refers to "pause.exe" in the last line. Does this mean it's only working on Windows? I though that Python was platform independent. \$\endgroup\$ Commented Mar 18, 2013 at 18:44
  • \$\begingroup\$ Gday. The pause.exe I only put in so that the python thingo doesn't vanish as soon as its finished executing, after I double click it on explorer. You are free to remove thsi line and voila it'll be platform independent. Using os dependent stuff is bad practice, and since I initially wrote it for me, I was being lazy :D At least I didn't concatenate paths with naive slashes nor use os specific delete-file functions. \$\endgroup\$
    – Peter pete
    Commented Mar 19, 2013 at 5:49
  • \$\begingroup\$ It's also written for Python 3.x versions. If you want it to be 2.x friendly just change all the print("something") to print "something" \$\endgroup\$
    – Peter pete
    Commented Mar 19, 2013 at 5:50

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