I have a dir with hundreds of images, some most of them are raw format (ending in CR2), but for some I've converted them to jpg, so I have both CR2 and JPEG.

How do I get all the files that end both in jpg and cr2 and move them to another dir.

so ls *.jpg would give me all the ones that end in jpg and from there I need to find those end in cr2? how do I do that? how would I then move them?


I'd use find(1) for this task:

find . -name '*.jpg' -exec /bin/sh -c 'A=`basename {} .jpg`.cr2 ; test -f $A && mv {} $A /other/dir' \;

A quick bash line would be:

for FILE in `ls *.jpg`; do BF=`basename $FILE .jpg`; 
   if test -e $BF.cr2 ; then mv $BF.jpg $BF.cr2 destdir/; fi; done
  • @AnonymousLurker: you are right - in this case the ls is totally utterly uselese, you could use instead just the *.jpg - I preferred to keep it in because the question included a ls *.jpg in case he wanted to replace it with a different command (and with generated image file names the problem with whitespaces in the names should usually not happen). – flolo Nov 1 '12 at 11:40

You'll need to write a script to do this with Python or Perl probably being your best bet.

Here is a script I wrote in Perl that does basically that (jpeg & raw files) and automates moving them to a "dated directory structure" (i.e. YYYY/MM-month/DD). It uses the Image::ExifTool library to extract the date of the photo to know where to put it.

For your exact question, you can see that it finds all .jpg files, works out the basename, and then checks for a matching .nef file.

#! /usr/bin/perl

$dryrun = 0;
$encode = 1;

use Image::ExifTool;
use Dumpvalue;
my $Dumper = new Dumpvalue();

@Months = qw(00 01-January 02-February 03-March 04-April 05-May 06-June 07-July 08-August 09-September 10-October 11-November 12-December);

$startdir = shift @ARGV;
die "error: no start directory specified\n" unless ($startdir ne "");
foreach $file (split(/\n/,`find "$startdir" -name "*.[Jj][Pp][Gg]" -print | sed -e 's,^\./,,'`)) {
  next if ($file =~ m,(^|/).xvpics/,);

  print STDERR "$file => ";
  my $exif = new Image::ExifTool;
  $info = $exif->ImageInfo($file);
  if (ref($info) != "HASH") {
    print STDERR "error: could not read exif data from '$file' ($@)\n";

  ($filename) = ($file =~ m,([^/]+)$,);
  #     $Dumper->dumpValue($info);
  #     next;
  #     exit(1);

  $date = $info->{"CreateDate"};
  #print STDERR $date," => ";

  unless (($y,$m,$d,$h,$n,$s) = ($date =~ m/^(\d\d\d\d)\D(\d\d)\D(\d\d)\D+(\d\d)\D(\d\d)\D(\d\d)($|\D)/)) {
    $date = $info->{"FileModifyDate"};
    unless (($y,$m,$d,$h,$n,$s) = ($date =~ m/^(\d\d\d\d)\D(\d\d)\D(\d\d)\D+(\d\d)\D(\d\d)\D(\d\d)($|\D)/)) {
      print STDERR "$file: no date for '$file' (skipped)\n";

  next if ($file eq "$outdir/$filename");
  system("mkdir","-p",$outdir) unless (-d $outdir || $dryrun);

  print STDERR "$outdir/".$filename;
  rename($file,"$outdir/".$filename) unless $dryrun;

  $jpgfile  = $filename;
  $file     =~ s/\....$/\.nef/;
  $filename =~ s/\....$/\.nef/;
  if (-f $file) {
    print STDERR " ($outdir/$filename)";
    rename($file,"$outdir/".$filename) unless $dryrun;
    chmod(0644, "$outdir/".$jpgfile) unless $dryrun;

  print STDERR "\n";

This is not high-quality code. :-) It's a hack I wrote for myself but should serve as a reasonable example.

  • thanks! I'll probably write my own then :)! thanks for the respond :)! – Meena Oct 31 '12 at 17:28

Change 'move2dir' in this script (twice) to wherever the files are supposed to end up, and then run it from the directory your jpg and cr2 files are in.

for file in `ls *jpg`
  if [ -e ${file/%jpg/cr2} ] 
    mv $file move2dir/
    mv $cr2file move2dir/
    echo moved $file and $cr2file

Your Answer

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