¿Cómo eliminar archivos JPG, pero solo si existe el archivo RAW correspondiente?

18

Mis primeras fotos (Canon G2) son todas JPG, pero cuando obtuve mi Nikon D90 inicialmente tomé JPG, luego cambié a RAW + JPG, y ahora me gustaría cambiar solo a RAW.

Tengo literalmente miles de fotos en mi HDD. Las fotos están en subdirectorios (por fecha) en un solo directorio llamado Importar.

Estoy a punto de importar todas estas fotos en Lightroom 3.0, sin embargo, me gustaría eliminar todos los archivos JPG, pero solo donde ya hay un archivo RAW correspondiente (es decir, ya no quiero mantener las versiones JPG y RAW de los mismos archivo).

Si puedo hacer esto fácilmente dentro de Lightroom (después de importar todo, incluidos los archivos JPG duplicados), sería genial. También estaría bien si hubiera una manera fácil de hacer esto antes de importar los archivos (pero con suerte esto no implicaría tener que visitar todos los directorios en busca de nombres de archivo con extensiones JPG y NEF).

¿Alguien sabe de una manera de hacer esto (en Lightroom, o con alguna herramienta / script en Windows)?

seanmc
fuente
¿Todos sus archivos jpg y RAW tienen como mínimo la misma cadena (se pueden agregar otros caracteres a cualquiera de los dos)? Por ejemplo, IMG_1234_portrait_picture.jpg y IMG_1234.CR2.
dpollitt
Creo que todos mis pares JPG / NEF tienen exactamente el mismo nombre de archivo (excepto la extensión).
seanmc
3
Voy a votar para mover esto a Stack Overflow, donde deberías obtener una respuesta en minutos =)
anon
1
@anon: ¿Cómo es exactamente esto en StackOverflow? Esta es definitivamente una pregunta sobre el tema aquí, ya que se trata de herramientas de administración de imágenes y edición de fotos. Fuera de una referencia tangencial al script ... esto no tiene nada que ver con la programación.
jrista
2
Estoy votando para cerrar esta pregunta como fuera de tema porque no se trata realmente de fotografía, se trata de administrar archivos que resultan ser fotografías. La pregunta y la respuesta serían las mismas si los dos tipos de archivos en cuestión fueran cualquier otro tipo de archivos que pudieran traducirse de un formulario a otro, como archivos .doc y .pdf, etc.
xiota

Respuestas:

24

En Windows , vaya a la carpeta y ejecútelo en un símbolo del sistema:

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

Básicamente, pasa por la carpeta actual, se ejecuta a través de los archivos NEF y elimina el JPG si está presente. Ignora cualquier error si el JPG no está allí.

Si desea subcarpetas, inclúyalas /sen el dircomando.

luego
fuente
3
¡Perfecto gracias! Por supuesto, antes de ejecutarlo por primera vez, cambié "del" a "echo". Luego ejecuté "ayuda para" para entender lo que estaba haciendo. Obviamente ha pasado mucho tiempo desde que vi las secuencias de comandos del símbolo del sistema, porque no tenía idea de que el comando "para" tenía tantas opciones.
seanmc
¡No hay problema! Como estaba probando, también usé "echo" =) Para ver más resultados, elimine "2> nul". Tenía la intención de hacer algo así para mis propios archivos NEF / JPG, y esta era la oportunidad perfecta.
anon
7

Aquí hay una versión modificada del script Python de Tomy . Diferencias:

  • múltiples extensiones sin procesar permitidas
  • elimine jpg solo si los pares están en la misma carpeta (evite la eliminación accidental de un jpg denominado como un archivo sin formato en otra carpeta)
  • insensible a mayúsculas y minúsculas

#!/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)
Renaud B.
fuente
Gran guión. Lo usaré porque tiene muchas failovers buenas. Sin embargo, debe agregar esta línea #!/usr/bin/env pythonal principio. De lo contrario, tuve errores extraños de ImageMagick (parece que mi Mac abre archivos .py con ImageMagick)
therealmarv
Solo para tu información: también parece que no funciona cuando los archivos están realmente nombrados .jPg. Tampoco funciona cuando los archivos están en el disco externo y el directorio de residuos, por ejemplo, en el /homedirectorio.
therealmarv
algunas correcciones: gist.github.com/therealmarv/ec603bd4a91d51092a18
therealmarv el
@therealmarv: en realidad lo que está sucediendo con ImageMagick es que el script se abre en el shell, no ImageMagick, pero "importar" es el nombre de una herramienta ImageMagick.
Max
6

Aquí hay un script de Python que mueve JPGarchivos cuando no RAWexiste un archivo correspondiente . ¡Útil en 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)
ttaveira
fuente
5
  • Crea una biblioteca vacía
  • En el menú principal de Lightroom, elija Edición> Preferencias (Windows) o Lightroom> Preferencias (Mac OS).
  • En las preferencias generales, desmarque "Tratar archivos JPEG junto a archivos sin formato como fotos separadas"
    • Este debería ser el predeterminado.
  • Importe todos sus archivos (puede seleccionar subcarpetas de búsqueda), diciéndole que se mueva a una nueva ubicación
  • Los archivos JPG que tienen archivos RAW se dejarán en la ubicación original para que los elimine

Según tengo entendido, la miniatura en lightroom puede decir RAW + JPG, pero el JPG en realidad no está almacenado ni accesible de ninguna manera.

También puede escribir un script por lotes bastante simple con cualquier lenguaje de programación.

Eruditass
fuente
2

Me gusta el script bash para OS X (por T.Toivonen ), pero he notado que hay algunos problemas.

  • No le gustaban los nombres de mi directorio, que contienen espacios. Eso requirió un manejo un poco diferente del comando find.

  • El script original solo funciona para extensiones en minúsculas. He mejorado ligeramente esa parte del script para tener en cuenta las extensiones que también están en mayúsculas. Tenga en cuenta que solo acepta DNG+JPGo dng+jpgempareja, e ignorará cualquier combinación como DNG+jpgo DnG+JpG.

  • La solución original propuso solo una wastedirubicación, mientras que mi solución permite crear un subdirectorio en cada rama del directorio a medida que viaja. Define un nombre del directorio antes del bucle.

  • Me gusta ver lo que está pasando, sobre todo cuando mvo rmse utilizan los comandos;)

Por el bien del espacio, solo estoy mostrando la última parte del guión, desde la configuración de a basedir, wastediry el bucle.

[...]

#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
Filip Wolak
fuente
La pregunta estaba etiquetada como "ventanas", por lo que podría decir cómo hacer que esto funcione en un sistema típico de Windows. Ejecuto Cygwin, por ejemplo (y planeo ver mejor esta respuesta cuando estoy en el escritorio, para cambiar un poco el comportamiento)
Chris H
2

Aquí hay una solución para bash(Linux o Mac OS X). En Windows, puede instalar Cygwin para obtener una copia 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
Ben Pingilley
fuente
2

Aquí hay otra bashversión usando find(Linux). Al igual que con la respuesta de Ben Pingilley , puede instalar Cygwin para obtener bash en Windows.

#!/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
bsod
fuente
1

Aquí está mi opinión sobre este tema. Muchas buenas ideas vinieron de guiones anteriores mencionados aquí.

Se trata de una escritura del golpe para OS X . Busca archivos que existan con el mismo nombre de archivo base y dng+jpgextensiones. Si jpgse encuentra un con exactamente el mismo nombre que dng, entonces ese nombre de archivo se muestra ( -e), el archivo se mueve ( -m) o se elimina ( -d).

Pasará por subcarpetas, por lo que puede usarlo para todo su catálogo o solo partes de él.

Para otras extensiones de archivo sin formato, simplemente sustituya *.dngel script con su extensión preferida.

Advertencia: podría tener dos imágenes diferentes con el mismo nombre, pero con una extensión diferente. Esas son las bajas inevitables de este guión.

Aquí se explica cómo usar el script:

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 

El uso básico funcionaría así:

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

Eso reflejaría todos los nombres de jpgarchivos que coinciden con el criterio de tener ambos dngy un jpgarchivo con el mismo nombre.

El resultado se vería así:

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.

Ahora, si quiero eliminar los archivos, simplemente cambiaría -ea -d:

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

O si quisiera mover los archivos / duplicados con los que lo ejecutaría -m.

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

Ahora los jpgarchivos duplicados estarían en/Volumes/photo/DNG/2015/duplicates

Aquí está el script: 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."
T. Toivonen
fuente
1

He aquí una bashsecuencia de comandos para Mac OS X . Se puede trabajar en Linux con algunos cambios.

#!/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

rmtrashes una utilidad que mueve archivos a la Papelera, en lugar de eliminarlos directamente. Puede obtenerlo de MacPorts así:

sudo port install rmtrash

Si desea evitar eso, simplemente reemplace rmtrashen el script con rm, que eliminará inmediatamente los JPGarchivos.

Manas Tungare
fuente
1

Escribí el siguiente script de Python . En comparación con el guión de ttaveira , hace un trabajo extra.

  • Busca en subdirectorios.
  • Crea el directorio de residuos de destino.
  • Elimina los archivos que ya existen en el directorio de residuos para evitar errores de movimiento.

# 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)
Para mi
fuente
2
Hola y bienvenidos a Photo.SE. ¿Cómo es tu respuesta diferente de la respuesta de ttaveira ?
Saaru Lindestøkke
El script realiza un trabajo adicional: también busca en todos los subdirectorios, crea un directorio de desperdicio de destino para jpg si no existe y elimina un jpg en lugar de moverlo si ya existe en el directorio de desperdicio (evita errores de movimiento)
Tomy
0

Trabajando en Mac OS X , me faltaba una verificación de la cordura para "mismo contenido" en las respuestas anteriores. Tenía nombres duplicados para diferentes imágenes porque había olvidado habilitar el contador de imágenes en mi cámara. Aquí está mi versión, que verifica la información EXIF ​​para el mismo tiempo de captura:

Necesitas correr

sudo port install rmtrash exiv2

antes de poder usar el siguiente comando. Fue escrito para comparar JPGcon NEFarchivos de mi Nikon D90. Ajuste las extensiones de archivo según sus necesidades.

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

sin el control de cordura, todo se volvería muy corto:

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