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? 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. 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. Commented Jun 19, 2016 at 10:49
  • perfect for deleting duplicate compiled typescript files :D 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 Commented Jun 20, 2016 at 15:17
  • @Gilles Due to above noted variable substitution you can't use sh instead bash 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.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.