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
3
  • 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
    Commented Jun 17, 2016 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. Commented Jun 17, 2016 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
    Commented Jun 17, 2016 at 18:26

4 Answers 4

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!

3
  • No, that doesn't work. You're testing for the existence of the first file only, and then deleting them all. Commented Jun 18, 2016 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
    Commented Jun 19, 2016 at 10:49
  • perfect for deleting duplicate compiled typescript files :D
    – velop
    Commented Oct 1, 2018 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
3
  • @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
    Commented Jun 20, 2016 at 15:17
  • @Gilles Due to above noted variable substitution you can't use sh instead bash
    – Costas
    Commented Jun 20, 2016 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. Commented Jun 20, 2016 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 ]]'\')

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .