Como excluir arquivos JPG, mas apenas se o arquivo RAW correspondente existir?


18

Minhas fotos antigas (Canon G2) são todas JPG, mas quando eu peguei a Nikon D90, eu inicialmente fotografei em JPG, depois mudei para RAW + JPG e agora gostaria de mudar apenas para RAW.

Tenho literalmente milhares de fotos no meu disco rígido. As fotos estão em subdiretórios (por data) em um único diretório chamado Importar.

Estou prestes a importar todas essas fotos para o Lightroom 3.0, no entanto, gostaria de excluir todos os arquivos JPG, mas apenas onde já houver um arquivo RAW correspondente (ou seja, não quero mais manter as versões JPG e RAW da mesma Arquivo).

Se eu puder fazer isso facilmente no Lightroom (depois de importar tudo, incluindo os arquivos JPG duplicados), isso seria ótimo. Também seria bom se houvesse uma maneira fácil de fazer isso antes de importar os arquivos (mas espero que isso não envolva a necessidade de visitar todos os diretórios procurando nomes de arquivos com extensões JPG e NEF).

Alguém conhece uma maneira de fazer isso (no Lightroom, ou com alguma ferramenta / script no Windows)?


Todos os seus arquivos jpg e RAW têm no mínimo a mesma sequência (outros caracteres podem ser adicionados a eles)? Por exemplo, IMG_1234_portrait_picture.jpg & IMG_1234.CR2.
dpollitt

Eu acho que todos os meus pares JPG / NEF têm exatamente o mesmo nome de arquivo (exceto a extensão).
seanmc

3
Vou votar para mover este para Stack Overflow, onde você deve obter uma resposta dentro de minutos =)
Anon

1
@anon: Como exatamente isso pertence ao StackOverflow? Definitivamente, essa é uma pergunta sobre o tópico, pois trata das ferramentas de gerenciamento de imagem e edição de fotos. Fora de uma referência tangencial ao script ... isso não tem nada a ver com programação.
jrista

2
Estou votando para encerrar esta questão como fora de tópico, porque não se trata realmente de fotografia, trata-se de gerenciar arquivos que, por acaso, são fotografias. A pergunta e resposta seria a mesma se os dois tipos de arquivos em questão foram quaisquer outros tipos de arquivos que pode ser traduzido de uma forma para outra, como arquivos .doc e .pdf, etc.
xiota

Respostas:


24

No Windows , vá para a pasta e execute isso em um prompt de comando:

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

Basicamente, ele percorre a pasta atual, executa os arquivos NEF e exclui o JPG, se presente. Ele ignora quaisquer erros se o JPG não estiver lá.

Se você deseja subpastas, inclua /sno dircomando


3
Perfeito, obrigado! É claro que antes de executá-lo pela primeira vez, mudei "del" para "eco". Então eu corri "help for" para entender o que estava fazendo. Obviamente, já faz muito tempo desde que eu analisei o script do prompt de comando, porque não fazia ideia de que o comando "for" tinha tantas opções.
seanmc

Sem problemas! Enquanto testava, também usei "echo" =) Para ver mais resultados, remova o "2> nul". Eu pretendia fazer algo assim para meus próprios arquivos NEF / JPG, e essa era a oportunidade perfeita.
anon

7

Aqui está uma versão modificada do script Python de Tomy . Diferenças:

  • várias extensões brutas permitidas
  • remova jpg apenas se os pares estiverem na mesma pasta (evite a remoção acidental de um jpg nomeado como um arquivo bruto em outra pasta)
  • insensível a maiú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)

ótimo roteiro. Vou usá-lo porque possui muitos bons failovers. No entanto, você deve adicionar esta linha #!/usr/bin/env pythonao início. Caso contrário, eu tinha erros ImageMagick estranhos (parece meu Mac aberto arquivos .py com ImageMagick)
therealmarv

Apenas FYI: também parece que não funciona quando os arquivos são realmente nomeados .jPg. Também não funciona quando os arquivos estão no disco externo e no diretório de resíduos, por exemplo, no /homediretório
Therealmarv


@therealmarv: na verdade, o que está acontecendo com o ImageMagick é que o script está sendo aberto no shell, não no ImageMagick, mas "import" é o nome de uma ferramenta ImageMagick.
Max

6

Aqui está um script Python que move JPGarquivos quando não RAWexiste um arquivo correspondente . Útil no 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)

5
  • Crie uma biblioteca vazia
  • No menu principal do Lightroom, escolha Editar> Preferências (Windows) ou Lightroom> Preferências (Mac OS).
  • Nas preferências Gerais, desmarque "Tratar arquivos JPEG ao lado de arquivos brutos como fotos separadas"
    • Esse deve ser o padrão.
  • Importe todos os seus arquivos (você pode selecionar subpastas de pesquisa), dizendo para mudar para um novo local
  • Os arquivos JPG que possuem arquivos RAW serão deixados no local original para você remover

Pelo que entendi, a miniatura no lightroom pode dizer RAW + JPG, mas o JPG não é realmente armazenado ou acessível de forma alguma.

Você também pode escrever um script em lote bastante simples com qualquer linguagem de programação.


2

Eu gosto do script bash para OS X (de T.Toivonen ), mas notei que existem alguns problemas.

  • Não gostou dos nomes dos meus diretórios, que contêm espaços. Isso exigiu um tratamento um pouco diferente do comando find.

  • O script original funciona apenas para extensões em minúsculas. Eu melhorei um pouco essa parte do script para considerar extensões que também estão em maiúsculas. Observe que ele aceita DNG+JPGou dng+jpgemparelha apenas e ignora quaisquer combinações como DNG+jpgou DnG+JpG.

  • A solução original propunha apenas um wastedirlocal, enquanto minha correção permite que um subdiretório seja criado em cada ramificação de diretório à medida que ele viaja. Você define um nome do diretório antes do loop.

  • Eu gosto de ver o que está acontecendo, especialmente quando mvou rmcomandos são usados;)

Por uma questão de espaço que estou mostrando apenas a última parte do script, a partir da criação de uma basedir, wastedireo loop.

[...]

#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

A pergunta foi marcada com "janelas", para que você possa dizer como isso pode funcionar em um sistema Windows típico. Eu corro Cygwin, por exemplo (e eu pretendo ter um melhor olhar para esta resposta quando estou no ambiente de trabalho, para mudar o comportamento de um bit)
Chris H

2

Aqui está uma solução para bash(Linux ou Mac OS X). No Windows, você pode instalar o Cygwin para obter uma cópia do 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

2

Aqui está outra bashversão usando find(Linux). Como na resposta de Ben Pingilley , você pode instalar o Cygwin para obter o bash no 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

1

Aqui está minha opinião sobre esse assunto. Muitas boas idéias vieram de scripts anteriores mencionados aqui.

Este é um script bash para OS X . Ele procura por arquivos que existem com o mesmo nome de arquivo e dng+jpgextensões base . Se a jpgfor encontrado exatamente com o mesmo nome que dng, então esse nome de arquivo será exibido ( -e), o arquivo será movido ( -m) ou excluído ( -d).

Ele passará por subpastas, para que você possa usá-lo em todo o catálogo ou apenas em partes dele.

Para outras extensões de arquivo simples, substitua *.dngno script a sua extensão preferida.

Aviso: você pode ter duas imagens diferentes com o mesmo nome, mas com extensões diferentes. Essas são vítimas inevitáveis ​​deste script.

Veja como usar o 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 

O uso básico funcionaria assim:

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

Isso ecoaria todos os nomes de jpgarquivos de arquivos que correspondem aos critérios de ter os dois dnge os jpgarquivos com o mesmo nome.

O resultado seria algo parecido com isto:

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.

Agora, se eu quiser excluir os arquivos, mudei -epara -d:

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

Ou se eu gostaria de mover os arquivos para / duplicados, eu o executaria -m.

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

Agora os jpgarquivos duplicados estariam em/Volumes/photo/DNG/2015/duplicates

Aqui está o 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."

1

Aqui está um bashroteiro para o Mac OS X . Ele pode trabalhar em Linux, com algumas alterações.

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

rmtrashé um utilitário que move os arquivos para a Lixeira, em vez de excluí-los completamente. Você pode obtê-lo no MacPorts assim:

sudo port install rmtrash

Se você quiser evitar isso, basta substituir rmtrashno script por rm, que excluirá imediatamente os JPGarquivos.


1

Eu escrevi o seguinte script Python . Comparado com o script de ttaveira , ele faz algum trabalho extra.

  • Procura em subdiretórios.
  • Cria o diretório de resíduos de destino.
  • Remove os arquivos que já existem no diretório de resíduos para evitar erros de movimentação.

# 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)

2
Olá e bem-vindo ao Photo.SE. Qual é a sua resposta diferente da resposta da ttaveira ?
Saaru Lindestøkke

O script faz um trabalho extra: também procura em todos os subdiretórios, cria um diretório de destino para jpg se ele não existir e remove um jpg em vez de se mover se ele já existir no diretório de resíduos (evita erros de movimentação)
Tomy

0

Trabalhando no Mac OS X , faltava uma verificação de sanidade para o "mesmo conteúdo" nas respostas anteriores. Eu tinha nomes duplicados para fotos diferentes porque tinha esquecido de ativar o contador de imagens na minha câmera. Aqui está minha versão, que verifica as informações EXIF ​​pelo mesmo tempo de captura:

Você precisa correr

sudo port install rmtrash exiv2

antes de poder usar o seguinte comando. Foi escrito para comparar JPGcom os NEFarquivos da minha Nikon D90. Ajuste as extensões de arquivo de acordo com suas necessidades.

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

sem a verificação de sanidade, tudo se tornaria muito curto:

find . -name \*.NEF |sed s/\.NEF/.JPG/g | xargs find 2>/dev/null | xargs rmtrash
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.