Wie lösche ich JPG-Dateien, aber nur wenn die passende RAW-Datei existiert?

Meine frühen (Canon G2) Fotos sind alle JPG, aber als ich meine Nikon D90 bekam, habe ich zunächst in JPG aufgenommen, dann zu RAW+JPG gewechselt, und jetzt möchte ich nur noch zu RAW wechseln.

Ich habe buchstäblich Tausende von Fotos auf meiner Festplatte. Die Fotos befinden sich in Unterverzeichnissen (nach Datum) unter einem einzigen Verzeichnis namens Import.

Ich bin dabei, alle diese Fotos in Lightroom 3.0 zu importieren, möchte jedoch alle JPG-Dateien löschen, aber nur dort, wo bereits eine entsprechende RAW-Datei vorhanden ist (dh ich möchte keine JPG- und RAW-Versionen derselben mehr behalten Datei).

Wenn ich dies problemlos in Lightroom tun könnte (nachdem ich alles importiert habe, einschließlich der doppelten JPG-Dateien), wäre das großartig. Es wäre auch in Ordnung, wenn es eine einfache Möglichkeit gäbe, dies vor dem Importieren der Dateien zu tun (aber hoffentlich würde dies nicht bedeuten, dass Sie jedes Verzeichnis besuchen müssten, um nach Dateinamen mit JPG- und NEF-Erweiterungen zu suchen).

Kennt jemand eine Möglichkeit, dies zu tun (in Lightroom oder mit einem Tool/Skript in Windows)?

Haben alle Ihre JPG-Dateien und RAW-Dateien mindestens dieselbe Zeichenfolge (andere Zeichen können beiden hinzugefügt werden)? ZB IMG_1234_portrait_picture.jpg & IMG_1234.CR2.
Ich denke, dass alle meine JPG/NEF-Paare genau denselben Dateinamen haben (mit Ausnahme der Erweiterung).
Ich werde dafür stimmen, dies nach Stack Overflow zu verschieben, wo Sie innerhalb von Minuten eine Antwort erhalten sollten =)
@anon: Wie genau gehört das zu StackOverflow? Dies ist hier definitiv eine themenbezogene Frage, da es um Bildverwaltungs- und Fotobearbeitungswerkzeuge geht. Abgesehen von einer tangentialen Bezugnahme auf Skripte ... hat dies nichts mit Programmierung zu tun.
@jrista - Der Fragesteller sagte, es sei in Ordnung, die Dateien/Ordner vor dem Import in Lightroom zu verarbeiten. Für mich wäre eine Scripting-Lösung ideal, weil sie toolunabhängig, schneller, portabler und anpassbar wäre. Im abstrakten Sinne ist es sogar unabhängig von der Art der Dateien, mit denen wir es zu tun haben. Aber andererseits bin ich Programmierer =)
@anon Es ist definitiv keine Programmierfrage , also, obwohl es auf Superuser passen mag, sehe ich es hier auch als themenbezogen an, da es eine starke und spezifische Anwendung für die Verwaltung von Fotos ist.
@Rowland - Fair genug =)
Ich denke, es liegt im breiten Rahmen dessen, was wir zum Thema vereinbart haben – aber ich denke auch, dass es nicht wirklich fotospezifisch ist und auf einer SE-Site mit einem größeren Umfang möglicherweise mehr und schnellere Antworten erhalten hätte. Aber wir haben jetzt einige Antworten, also denke ich, dass alles gut ist. :)
Als ich die Frage eintippte, wurde mir klar, dass die Problemdomäne nicht wirklich fotografisch war und dass die einfachste Antwort mit ziemlicher Sicherheit die Verwendung eines Skripts wäre (und die Antwort von Anon funktioniert perfekt, danke!), Aber ich habe die Frage trotzdem hinzugefügt weil Ich hatte gehofft, etwas Neues über Lightroom zu lernen.
Ich stimme dafür, diese Frage als nicht zum Thema gehörend zu schließen, da es hier nicht wirklich um Fotografie geht, sondern um die Verwaltung von Dateien, die zufällig Fotos sind. Die Frage und Antwort wären die gleichen, wenn die beiden fraglichen Dateitypen andere Dateitypen wären, die von einem Formular in ein anderes übersetzt werden könnten, wie z. B. .doc- und .pdf-Dateien usw.

Antworten (11)

Wechseln Sie unter Windows zu dem Ordner und führen Sie diesen in einer Eingabeaufforderung aus:

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

Grundsätzlich durchläuft es den aktuellen Ordner, durchläuft die NEF-Dateien und löscht das JPG, falls vorhanden. Es ignoriert alle Fehler, wenn das JPG nicht vorhanden ist.

Wenn Sie Unterordner wünschen, schließen Sie /ssie in den dirBefehl ein.

Perfekt danke! Bevor ich es das erste Mal ausgeführt habe, habe ich natürlich "del" in "echo" geändert. Dann habe ich "Hilfe für" ausgeführt, um zu verstehen, was es tat. Es ist offensichtlich schon lange her, dass ich mich mit Befehlseingabeaufforderungsskripten beschäftigt habe, weil ich nicht wusste, dass der „for“-Befehl so viele Optionen hat.
Kein Problem! Beim Testen habe ich auch "echo" verwendet =) Um mehr Ausgabe zu sehen, entfernen Sie "2> nul". Ich hatte vor, so etwas für meine eigenen NEF/JPG-Dateien zu machen, und das war die perfekte Gelegenheit.
Fantastisch. Aufräumen und alte raw+jpeg-Ordnerstruktur leicht gemacht mit einem ordentlichen cmd :)

Hier ist eine modifizierte Version von Tomys Python-Skript . Unterschiede:

  • mehrere Raw-Erweiterungen erlaubt
  • Entfernen Sie JPG nur, wenn sich die Paare im selben Ordner befinden (vermeiden Sie das versehentliche Entfernen einer JPG-Datei mit dem Namen einer Rohdatei in einem anderen Ordner).
  • Groß- und Kleinschreibung

#!/usr/bin/env python
# Script:      remove_jpg_if_raw_exists.py
#
# Description: This script looks in all sub directories for
#              pairs of JPG and RAW files.
#              For each pair found the JPG is moved to a
#              waste basket directory.
#              Otherwise JPG is kept.
#
# Author:      Thomas Dahlmann
# Modified by: Renaud Boitouzet

import os
import shutil

# define your file extensions here, case is ignored.
# Please start with a dot.
# multiple raw extensions allowed, single jpg extension only
raw_extensions = (".Dng", ".cR2", ".nef", ".crw")
jpg_extension = ".jPg"

# define waste basket directory here. Include trainling slash or backslash.
# Windows : waste_dir = "C:\path\to\waste\"
waste_dir = "/Users/marvin/Pictures/waste/"

##### do not modify below ##########

# find files
def locate(folder, extensions):
    '''Locate files in directory with given extensions'''
    for filename in os.listdir(folder):
        if filename.endswith(extensions):
            yield os.path.join(folder, filename)

# make waste basket dir
if not os.path.exists(waste_dir):
    os.makedirs(waste_dir)

# Make search case insensitive
raw_ext = tuple(map(str.lower,raw_extensions)) + tuple(map(str.upper,raw_extensions))
jpg_ext = (jpg_extension.lower(), jpg_extension.upper())

root=os.curdir
#find subdirectories
for path, dirs, files in os.walk(os.path.abspath(root)):
    print path
    raw_hash = {}
    for raw in locate(path, raw_ext):
        base_name = os.path.basename(raw)
        base_name = os.path.splitext(base_name)[0]
        raw_hash[base_name] = True

    # find pairs and move jpgs of pairs to waste basket
    for jpg in locate(path, jpg_ext):
        base_name = os.path.basename(jpg)
        base_name = os.path.splitext(base_name)[0]
        if base_name in raw_hash:
            jpg_base_name_with_ext = base_name + jpg_extension
            new_jpg = waste_dir + jpg_base_name_with_ext
            print "%s: %s = %s => %s" % (path, base_name, jpg, waste_dir)
            if os.path.exists(new_jpg):
                os.remove(jpg)
            else:
                shutil.move(jpg, new_jpg)
tolles Drehbuch. Ich werde es verwenden, weil es viele gute Failover hat. Sie sollten diese Zeile #!/usr/bin/env pythonjedoch am Anfang hinzufügen. Ansonsten hatte ich seltsame ImageMagick-Fehler (scheint mein Mac öffnet .py-Dateien mit ImageMagick)
Nur zur Information: Es scheint auch nicht zu funktionieren, wenn die Dateien wirklich benannt sind .jPg. Es funktioniert auch nicht, wenn sich Dateien auf einer externen Platte befinden und das Verzeichnis zB in /homedir verschwendet wird.
@therealmarv: Eigentlich passiert mit ImageMagick, dass das Skript in der Shell geöffnet wird, nicht ImageMagick, aber "Import" ist der Name eines ImageMagick-Tools.

Hier ist ein Python-Skript , das JPGDateien verschiebt, wenn keine entsprechende RAWDatei vorhanden ist. Nützlich unter Mac OS X !

import os
import shutil

raw_ext = '.CR2'
jpg_ext = '.JPG'
destination = '/Users/JohnSmith/Desktop/jpgs/'

for filename in os.listdir('.'):
    (shortname, extension) = os.path.splitext(filename)

    if extension == raw_ext:
        if os.path.isfile(shortname + jpg_ext):
            print 'Moving ' + shortname + jpg_ext + '...'
            shutil.move(shortname + jpg_ext, destination)
  • Erstellen Sie eine leere Bibliothek
  • Wählen Sie im Hauptmenü von Lightroom „Bearbeiten“ > „Voreinstellungen“ (Windows) bzw. „Lightroom“ > „Voreinstellungen“ (Mac OS).
  • Deaktivieren Sie in den allgemeinen Einstellungen „JPEG-Dateien neben RAW-Dateien als separate Fotos behandeln“.
    • Dies sollte die Voreinstellung sein.
  • Importieren Sie alle Ihre Dateien (Sie können Unterordner durchsuchen) und weisen Sie sie an , an einen neuen Speicherort zu wechseln
  • Die JPG-Dateien mit RAW-Dateien bleiben am ursprünglichen Speicherort, damit Sie sie entfernen können

So wie ich es verstehe, könnte das Miniaturbild in Lightroom RAW + JPG anzeigen, aber das JPG wird nicht wirklich gespeichert oder ist in irgendeiner Weise zugänglich.

Sie können auch mit jeder Programmiersprache ein ziemlich einfaches Batch-Skript schreiben.

Ich mag das Bash-Skript für OS X (von T.Toivonen ), aber ich habe bemerkt, dass es ein paar Probleme gibt.

  • Es mochte meine Verzeichnisnamen nicht, die Leerzeichen enthalten. Das erforderte eine etwas andere Handhabung des Find-Befehls.

  • Das ursprüngliche Skript funktioniert nur für Erweiterungen in Kleinbuchstaben. Ich habe diesen Teil des Skripts leicht verbessert, um auch Erweiterungen in Großbuchstaben zu berücksichtigen. DNG+JPGBeachten Sie, dass es nur oder Paare akzeptiert dng+jpgund alle Kombinationen wie DNG+jpgoder ignoriert DnG+JpG.

  • Die ursprüngliche Lösung schlug nur einen wastedirSpeicherort vor, während mein Fix es ermöglicht, ein Unterverzeichnis in jedem Verzeichniszweig zu erstellen, während er sich bewegt. Vor der Schleife legen Sie einen Namen des Verzeichnisses fest.

  • Ich sehe gerne, was los ist, besonders wenn mvoder rmBefehle verwendet werden ;)

Aus Platzgründen zeige ich nur den letzten Teil des Skripts, ab dem Setzen von a basedirund wastedirder Schleife.

[...]

#Now set it as a basedir
BASEDIR=$arg
WASTEDIR=duplicates
find "$BASEDIR" -iname '*.dng' -print0 | while read -d $'\0' filename 
    do
    filepath="${filename%/*}"
    basename="${filename##*/}"
    prefix="${basename%%.*}"
    suffix=${filename##*.}
    if [[ "$suffix" =~ [A-Z] ]]; then rsuffix="JPG"; else rsuffix="jpg"; fi 
    if [ -e "$filepath/$prefix.$rsuffix" ]; then
        let counter="$counter+1"
        if (( $isSetE==1 )); then
            echo "FOUND: $filepath/$prefix.$rsuffix"
        fi
        if (( $isSetM==1 )); then
            echo "Moving $filepath/$prefix.$rsuffix to $filepath/$WASTEDIR"
            if [ ! -d "$filepath/$WASTEDIR" ]; then mkdir "$filepath/$WASTEDIR"; fi
            mv "$filepath/$prefix.$rsuffix" "$filepath/$WASTEDIR"
        fi
        if (( $isSetD==1 )); then
            echo "Removing duplicate $filepath/$prefix.$rsuffix"
            rm "$filepath/$prefix.$rsuffix"
        fi
    fi
done
Die Frage war mit "Windows" gekennzeichnet, sodass Sie sagen konnten, wie dies in einem typischen Windows-System zum Laufen gebracht werden könnte. Ich führe zum Beispiel Cygwin aus (und ich plane, mir diese Antwort besser anzusehen, wenn ich auf dem Desktop bin, um das Verhalten ein wenig zu ändern).

Hier ist eine Lösung für bash(Linux oder Mac OS X). Unter Windows können Sie Cygwin installieren , um eine Kopie von bash.

keep=$(ls | grep -v ps | grep -A1 JPG | grep NEF)
for i in $keep ; do
   mv $i $i.keep
done

ls | egrep -v '(JPG|keep)' | xargs rm -f

change=$(ls | grep keep | sed 's/.keep//g')
for i in $change ; do
   mv $i.keep $i
done

Hier ist eine andere bashVersion mit find(Linux). Wie bei Ben Pingilleys Antwort können Sie Cygwin installieren , um Bash unter Windows zu erhalten.

#!/bin/bash
read -p "please enter file suffix for raw format (e.g ORF, NEF, CR2): " suffix

find . -type f -iname "*.${suffix}" | \
while read line
do
  lowercase=$(echo "$line" | sed "s/${suffix}/jpg/gi")
  uppercase=$(echo "$line" | sed "s/${suffix}/JPG/gi")

  if [ -f "${lowercase}" ]
  then
    rm -v "${lowercase}"
  elif [ -f "${uppercase}" ]
  then
    rm -v "${uppercase}"
  else
    echo "${line}: no jpg present"
  fi
done

Hier ist meine Meinung zu diesem Thema. Viele gute Ideen stammen aus früheren Skripten, die hier erwähnt wurden.

Dies ist ein Bash-Skript für OS X. Es sucht nach Dateien, die mit demselben Basisdateinamen und denselben dng+jpgErweiterungen vorhanden sind. Wenn eine jpgmit genau demselben Namen wie gefunden dngwird, wird dieser Dateiname angezeigt ( -e), die Datei verschoben ( -m) oder gelöscht ( -d).

Es durchläuft Unterordner, sodass Sie es für Ihren gesamten Katalog oder nur Teile davon verwenden können.

Für andere RAW-Dateierweiterungen ersetzen Sie einfach *.dngdas Skript durch Ihre bevorzugte Erweiterung.

Warnung: Sie könnten zwei verschiedene Bilder mit demselben Namen, aber unterschiedlicher Erweiterung haben. Das sind unvermeidliche Opfer dieses Drehbuchs.

So verwenden Sie das Skript:

Usage: dng-jpg.sh [-m <path>] [-d <path>] [-e <path>] [-h]

-m: for move   (moves files to <path>/duplicates)
-d: for delete (deletes duplicate files)
-e: for echo   (lists duplicate files)
-h: for help 

Die grundlegende Verwendung würde wie folgt funktionieren:

$ ./dng-jpg.sh -e /Volumes/photo/DNG/2015

Das würde alle Dateinamen von jpgDateien wiedergeben, die den Kriterien entsprechen, sowohl dngals auch jpgDateien mit demselben Namen zu haben.

Das Ergebnis würde in etwa so aussehen:

Echo selected with path: /Volumes/photo/DNG/2015
/Volumes/photo/DNG/2015/03/18/2015-03-18_02-11-17.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-10-50.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-10-56.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-11-39.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-11-54.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-12-26.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-12-43.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-13-21.jpg
/Volumes/photo/DNG/2015/06/01/2015-06-01_05-13-56.jpg
9 files found.

Wenn ich jetzt die Dateien löschen möchte, würde ich einfach wechseln -ezu -d:

$ ./dng-jpg.sh -d /Volumes/photo/DNG/2015

Oder wenn ich die Dateien nach /duplicates verschieben möchte, würde ich es mit ausführen -m.

$ ./dng-jpg.sh -m /Volumes/photo/DNG/2015

jpgJetzt wären die doppelten Dateien drin/Volumes/photo/DNG/2015/duplicates

Hier ist das Skript: dng-jpg.sh

#!/bin/bash

# Init variables
isSetM=0
isSetD=0
isSetE=0
isSetCount=0
counter=0

#Display usage info
usage() {

    cat <<EOF

Usage: dng-jpg.sh [-m <path>] [-d <path>] [-e <path>] [-h]

-m: for move   (moves files to <path>/duplicates)
-d: for delete (deletes duplicate files)
-e: for echo   (lists duplicate files)
-h: for help 

EOF
  exit 1
}

#Check for parameters
while getopts ":m:d:e:h" opt; do
  case ${opt} in
    m)
        isSetM=1
        let isSetCount="$isSetCount+1"
        arg=${OPTARG}
      echo "Move selected with path:" $arg
      ;;
    d)
        isSetD=1
        let isSetCount="$isSetCount+1"
        arg=${OPTARG}
      echo "Delete selected with path:" $arg
      ;;
    e)
        isSetE=1
        let isSetCount="$isSetCount+1"
        arg=${OPTARG}
      echo "Echo selected with path:" $arg
      ;;
    h)
        let isSetCount="$isSetCount+1"
        usage
      ;;
    \?)
      echo "Invalid option: -$OPTARG" >&2
      usage
      ;;
    :)
      echo "Option -$OPTARG requires a directory argument." >&2
      usage
      ;;
    *)
      usage
      ;;
  esac
done

# If no parameters, show usage help and exit
if test -z "$1"; then
    usage
fi

# If multiple parameters (not counting -a), show usage help and exit
if (($isSetCount > 1)); then
    usage
fi

#Verify directory
if [ ! -d "$arg" ]; then
  echo "$arg is not a path to a directory." >&2
  usage
fi

#Now set it as a basedir
BASEDIR=$arg
WASTEDIR="$BASEDIR/duplicates/"
if (( $isSetM==1 )); then
    mkdir $WASTEDIR
fi

for filename in $(find $BASEDIR -name '*.dng' -exec echo {} \; | sort); do
   prefix=${filename%.dng}
    if [ -e "$prefix.jpg" ]; then
        let counter="$counter+1"
        if (( $isSetE==1 )); then
            echo "$prefix.jpg"
        fi
        if (( $isSetM==1 )); then
            mv $prefix.jpg $WASTEDIR
        fi
        if (( $isSetD==1 )); then
            rm $prefix.jpg
        fi
    fi
done

echo "$counter files found."

Hier ist ein bashSkript für Mac OS X. Es kann mit einigen Änderungen unter Linux funktionieren.

#!/bin/bash
read -p "Delete JPEGs when DNG exists? Ctrl-C to cancel. [Enter] to continue: "

for FILE in *.dng; do
  JPG_FILE=$(echo "$FILE" | sed "s/dng/jpg/g")
  rmtrash "${JPG_FILE}" 1>/dev/null
done

rmtrashist ein Dienstprogramm, das Dateien in den Papierkorb verschiebt, anstatt sie sofort zu löschen. Sie können es folgendermaßen von MacPorts erhalten:

sudo port install rmtrash

Wenn Sie das vermeiden möchten, ersetzen Sie einfach rmtrashim Skript durch , wodurch die Dateien rmsofort gelöscht werden.JPG

Ich habe das folgende Python-Skript geschrieben . Verglichen mit dem Skript von ttaveira macht es etwas mehr Arbeit.

  • Sucht in Unterverzeichnissen.
  • Erstellt ein Zielabfallverzeichnis.
  • Entfernt Dateien, die bereits im Waste-Verzeichnis vorhanden sind, um Verschiebungsfehler zu vermeiden.

# Script:      remove_jpg_if_raw_exists.py
#
# Description: This script looks in all sub directories for
#              pairs of JPG and RAW files.
#              For each pair found the JPG is moved to a
#              waste basket directory.
#              Otherwise JPG is kept.
#
# Author:      Thomas Dahlmann

import os, fnmatch

# define your file extensions here, case is ignored
raw_extension = "nef"
jpg_extension = "jpg"

# define waste basket directory here
waste_dir = "c:\image_waste_basked"

##### do not modify below ##########

# recursive find files 
def locate(pattern, root=os.curdir):
    '''Locate all files matching supplied filename pattern 
    in and below root directory.'''
    for path, dirs, files in os.walk(os.path.abspath(root)):
        for filename in fnmatch.filter(files, pattern):
            yield os.path.join(path, filename) 

# get base names from raw's
raw_hash = {}
for raw in locate("*." + raw_extension):
    base_name = os.path.basename(raw)
    base_name = os.path.splitext(base_name)[0]
    raw_hash[base_name] = True

# make waste basket dir
if not os.path.exists(waste_dir):
    os.makedirs(waste_dir)

# find pairs and move jpgs of pairs to waste basket    
for jpg in locate("*." + jpg_extension):
    base_name = os.path.basename(jpg)
    base_name = os.path.splitext(base_name)[0]
    if base_name in raw_hash:
        jpg_base_name_with_ext = base_name + "." + jpg_extension
        new_jpg = waste_dir + "\\" + jpg_base_name_with_ext
        print "%s => %s" % (jpg, waste_dir)
        if os.path.exists(new_jpg):
            os.remove(jpg)
        else:
            os.rename(jpg, new_jpg)
Hallo und willkommen bei Photo.SE. Wie unterscheidet sich Ihre Antwort von der Antwort von ttaveira ?
Das Skript macht einige zusätzliche Arbeit: sucht auch in allen Unterverzeichnissen, erstellt ein Ziel-Abfallverzeichnis für JPGs, wenn es nicht existiert, und entfernt ein JPG, anstatt es zu verschieben, wenn es bereits im Abfallverzeichnis existiert (vermeidet Verschiebungsfehler).

Bei der Arbeit an Mac OS X fehlte mir in den vorherigen Antworten eine Plausibilitätsprüfung für "gleichen Inhalt". Ich hatte doppelte Namen für verschiedene Bilder, weil ich vergessen hatte, den Bildzähler in meiner Kamera zu aktivieren. Hier ist meine Version, die die EXIF-Informationen auf dieselbe Aufnahmezeit überprüft:

Du musst laufen

sudo port install rmtrash exiv2

bevor Sie den folgenden Befehl verwenden können. Es wurde geschrieben, um es JPGmit NEFDateien meiner Nikon D90 zu vergleichen. Passen Sie die Dateierweiterungen Ihren Bedürfnissen an.

find . -name \*.NEF |sed s/\.NEF/.JPG/g | xargs find 2>/dev/null | \
xargs perl -e 'foreach(@ARGV) {my $jpg=$_;my $nef=s/\.JPG/.NEF/r; my $tjpg = `exiv2 -g Exif.Photo.DateTimeOriginal -pt $jpg`; my $nef=s/\.JPG/.NEF/r; my $tnef = `exiv2 -g Exif.Photo.DateTimeOriginal -pt $nef`; if($tjpg eq $tnef) {print "$jpg\n"}}' | \
xargs rmtrash

ohne Plausibilitätsprüfung würde das Ganze zu einem sehr kurzen Einzeiler werden:

find . -name \*.NEF |sed s/\.NEF/.JPG/g | xargs find 2>/dev/null | xargs rmtrash