1

I have a series of preview images and RAW files in a directory structure (shown below), I quickly review the preview images, and delete those that I don't want.

The RAW files are in a RAW subdirectory of each directory.

What I'm looking for is a bash command, or small script that will delete the RAW file, if a file with the corresponding preview image doesn't exist.

The subdir tree looks like:

2016/
     05/
        image1.jpg
        image2.jpg
        image3.jpg
        RAW/
            image1.RAW
            image2.RAW
            image3.RAW

As you can imagine there are multiple year and month subdirectories, occasionally if there's been a large event, there may be a further set of subdirs below the month subdir, (as shown below) so ideally I'm looking for something I can chuck into cron to run once a day/week to just tidy up after any review/changes I make.

2016/
     05/
        image1.jpg
        image2.jpg
        image3.jpg
        RAW/
            image1.RAW
            image2.RAW
            image3.RAW
        event 1/
                image4.jpg
                image5.jpg
                image6.jpg
                RAW/
                    image4.RAW
                    image5.RAW
                    image6.RAW
        event 2/
                image7.jpg
                image8.jpg
                image9.jpg
                RAW/
                    image7.RAW
                    image8.RAW
                    image9.RAW
  • Have you tried looking at cut to trim off the extension and just try an if statement to test if a file starting with the same name exists? – Centimane Jun 17 '16 at 17:48
  • 1
    Show us what you've done so far and we'll help you complete it. Note that I would use sed s/.jpg/.RAW/ for the filename change and a few loops to deal with the directory structure. – Julie Pelletier Jun 17 '16 at 18:00
  • 2
    @JuliePelletier If you're going to sed the extensions, better to use sed s/\.jpg$/.RAW/ to escape the wildcard . and to make sure you only match on the end of a filename. – Centimane Jun 17 '16 at 18:26
2

The easier will be the Costas way without any scripting but using builtin, proper dir and proper command substitution. (not tested)

find 2016 -name '*.RAW' -execdir sh -c '[ ! -f "../${0%.RAW}.jpg" ]' {} \; -delete

Writing a bash script doing this is trivial, some globstar (**) and some [[]] and done!

  • No, that doesn't work. You're testing for the existence of the first file only, and then deleting them all. – Gilles Jun 18 '16 at 19:57
  • Sure, I've test it and even Costa's way doesn't work. I've created the script and the test. It's really a shame that I didn't test it. Sorry about that. – more2000 Jun 19 '16 at 10:49
  • perfect for deleting duplicate compiled typescript files :D – velop Oct 1 '18 at 13:25
1

Tested and working.

#!/usr/bin/env bash
#delete RAW if Preview img doesn't exists

createTest() {
  local dir=$1
  rm -rf "$dir"
  mkdir -p "$dir"/05/{"event 1","event 2"}/RAW/
  mkdir -p "$dir"/05/RAW
  touch "$dir"/05/RAW/image{1..3}.RAW; touch "$dir"/05/image{1..2}.jpg
  touch "$dir/05/event 1/RAW/"image{4..6}.RAW; touch "$dir/05/event 1/"image{4..5}.jpg
  touch "$dir/05/event 2/RAW/"image{7..9}.RAW; touch "$dir/05/event 2/"image{7..8}.jpg
}

deleteRAW() {
  local jpg= 
  local t=
  shopt -s globstar; 
  for raw in "$1"/**/*.RAW; do 
    t=${raw##*/}
    jpg=${raw%/*}/../${t%.*}.jpg
    if [[ ! -f $jpg ]]; then
      rm -f "$raw"
      echo "Removed $raw"
    fi
  done;
}

for dir; do
   createTest "$dir"
   deleteRAW "$dir"
done

Testing:

]➬./delete.sh 2016
Removed 2016/05/RAW/image3.RAW
Removed 2016/05/event 1/RAW/image6.RAW
Removed 2016/05/event 2/RAW/image9.RAW

Testing with spaces:

]➬./delete.sh "2016 spaces"
Removed 2016 spaces/05/RAW/image3.RAW
Removed 2016 spaces/05/event 1/RAW/image6.RAW
Removed 2016 spaces/05/event 2/RAW/image9.RAW

With multiple dirs:

 ]➬./delete.sh "2016 spaces" 2017
 Removed 2016 spaces/05/RAW/image3.RAW
 Removed 2016 spaces/05/event 1/RAW/image6.RAW
 Removed 2016 spaces/05/event 2/RAW/image9.RAW
 Removed 2017/05/RAW/image3.RAW
 Removed 2017/05/event 1/RAW/image6.RAW
 Removed 2017/05/event 2/RAW/image9.RAW

You can feel free to test it using other solutions commenting out the deleteRAW call in the last line.

for dir; do
   createTest "$dir"
   #deleteRAW "$dir"      
done

Cheers and best luck. :)

1

If correspondence based on the same names but different extention

find 2016 -name '*.RAW' -exec bash -c '[ ! -f "${0//RAW/}jpg" ]' {} \; -delete
  • @Wildcard I insist for "${0//RAW/}jpg" to remove two entries of RAW in path: compare 2016/05/event1/image4.jpg and 2016/05/event1/RAW/image4.RAW – Costas Jun 20 '16 at 15:17
  • @Gilles Due to above noted variable substitution you can't use sh instead bash – Costas Jun 20 '16 at 15:19
  • Indeed. The version I edited doesn't need bash, but the original does. I hadn't noticed that the raw images were in a different directory and so the %.RAW version is incorrect. – Gilles Jun 20 '16 at 15:37
1

In zsh, you can use the e glob qualifier to filter wildcard matches.

rm **/*.RAW(e\''[[ ! -e ${REPLY//\/RAW\//\/}:r.jpg ]]'\')

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.