Làm cách nào để xóa các tệp JPG, nhưng chỉ khi tệp RAW phù hợp tồn tại?


18

Những bức ảnh đầu tiên của tôi (Canon G2) đều là JPG, nhưng khi tôi nhận được chiếc Nikon D90 của mình, ban đầu tôi đã chụp ở định dạng JPG, sau đó chuyển sang RAW + JPG và bây giờ tôi chỉ muốn chuyển sang RAW.

Tôi có hàng ngàn bức ảnh trên ổ cứng. Các bức ảnh nằm trong các thư mục con (theo ngày) trong một thư mục có tên là Nhập.

Tôi sắp nhập tất cả các ảnh này vào Lightroom 3.0, tuy nhiên, tôi muốn xóa tất cả các tệp JPG, nhưng chỉ khi đã có tệp RAW tương ứng (nghĩa là tôi không còn muốn giữ các phiên bản JPG và RAW giống nhau tập tin).

Nếu tôi có thể thực hiện việc này một cách dễ dàng trong Lightroom (sau khi nhập mọi thứ, bao gồm các tệp JPG trùng lặp) thì sẽ rất tuyệt. Cũng sẽ ổn nếu có một cách dễ dàng để làm điều này trước khi nhập tệp (nhưng hy vọng điều này sẽ không liên quan đến việc phải truy cập mọi thư mục tìm kiếm tên tệp có cả phần mở rộng JPG và NEF).

Có ai biết một cách để làm điều này (trong Lightroom, hoặc với một số công cụ / tập lệnh trong Windows) không?


Có phải tất cả các tệp jpg và tệp RAW của bạn có tối thiểu cùng một chuỗi (các ký tự khác có thể được thêm vào một trong hai) không? Ví dụ: IMG_1234_portrait_picture.jpg & IMG_1234.CR2.
dpollitt

Tôi nghĩ rằng tất cả các cặp JPG / NEF của tôi có cùng tên tệp (ngoại trừ phần mở rộng).
seanmc

3
Tôi sẽ bỏ phiếu để di chuyển này để Stack Overflow, nơi bạn sẽ nhận được một câu trả lời trong vòng vài phút =)
anon

1
@anon: Chính xác thì cái này thuộc về StackOverflow như thế nào? Đây chắc chắn là một câu hỏi về chủ đề ở đây, vì nó liên quan đến quản lý hình ảnh và các công cụ chỉnh sửa ảnh. Bên ngoài một tham chiếu tiếp tuyến đến kịch bản ... điều này không liên quan gì đến lập trình.
jrista

2
Tôi đang bỏ phiếu để đóng câu hỏi này ngoài chủ đề vì đây không thực sự là về nhiếp ảnh, đó là về việc quản lý các tệp chỉ là ảnh. Câu hỏi và câu trả lời sẽ giống nhau nếu hai loại tệp trong câu hỏi là bất kỳ loại tệp nào khác có thể được dịch từ dạng này sang dạng khác, chẳng hạn như tệp .doc và .pdf, v.v.
xiota

Câu trả lời:


24

Trên Windows , đi đến thư mục và chạy lệnh này trong dấu nhắc lệnh:

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

Về cơ bản, nó đi qua thư mục hiện tại, chạy qua các tệp NEF và xóa JPG nếu có. Nó bỏ qua mọi lỗi nếu JPG không có ở đó.

Nếu bạn muốn các thư mục con, bao gồm /strong dirlệnh.


3
Hoàn hảo, cảm ơn! Tất nhiên trước khi tôi chạy nó lần đầu tiên, tôi đã thay đổi "del" thành "echo". Sau đó, tôi chạy "trợ giúp" để hiểu những gì nó đang làm. Rõ ràng đã lâu rồi tôi mới xem kịch bản nhắc lệnh, bởi vì tôi không biết rằng lệnh "for" có quá nhiều tùy chọn.
seanmc

Không vấn đề gì! Khi tôi đang thử nghiệm, tôi cũng đã sử dụng "echo" =) Để xem thêm đầu ra, hãy xóa "2> nul." Tôi đã có ý định làm một cái gì đó như thế này cho các tệp NEF / JPG của riêng tôi và đây là cơ hội hoàn hảo.
anon

7

Đây là phiên bản sửa đổi của tập lệnh Python của Tomy . Sự khác biệt:

  • nhiều phần mở rộng thô được phép
  • chỉ xóa jpg nếu các cặp trong cùng một thư mục (tránh việc vô tình xóa một jpg có tên giống như một tệp thô trong một thư mục khác)
  • trường hợp không nhạy cảm

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

kịch bản tuyệt vời. Tôi sẽ sử dụng nó vì nó có nhiều lỗi tốt. Tuy nhiên, bạn nên thêm dòng này #!/usr/bin/env pythonvào đầu. Nếu không, tôi đã gặp lỗi ImageMagick lạ (có vẻ như mac của tôi mở các tệp .py bằng ImageMagick)
Therealmarv

Chỉ cần FYI: có vẻ như nó không hoạt động khi các tập tin thực sự được đặt tên .jPg. Nó cũng không hoạt động khi các tập tin nằm trên đĩa bên ngoài và thư mục thải, ví dụ như trong /homethư mục.
Therealmarv


@therealmarv: thực sự những gì đang xảy ra với ImageMagick là tập lệnh đang được mở trong trình bao, không phải ImageMagick, nhưng "nhập" là tên của một công cụ ImageMagick.
Tối đa

6

Đây là tập lệnh Python di chuyển JPGtệp khi không có RAWtệp tương ứng . Hữu ích trên 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
  • Tạo một thư viện trống
  • Từ menu chính của Lightroom, chọn Chỉnh sửa> Tùy chọn (Windows) hoặc Lightroom> Tùy chọn (Mac OS).
  • Trong tùy chọn chung, bỏ chọn "Xử lý tệp JPEG bên cạnh tệp thô dưới dạng ảnh riêng biệt"
    • Điều này nên được mặc định.
  • Nhập tất cả các tệp của bạn (bạn có thể chọn các thư mục con tìm kiếm), yêu cầu nó di chuyển đến một vị trí mới
  • Các tệp JPG có tệp RAW sẽ được để lại ở vị trí ban đầu để bạn xóa

Theo tôi hiểu, hình thu nhỏ trong lightroom có ​​thể nói RAW + JPG, nhưng JPG thực sự không được lưu trữ hoặc có thể truy cập theo bất kỳ cách nào.

Bạn cũng có thể viết một tập lệnh bó khá đơn giản với bất kỳ ngôn ngữ lập trình nào.


2

Tôi thích tập lệnh bash cho OS X (của T.Toivonen ), nhưng tôi nhận thấy có một vài vấn đề.

  • Nó không thích tên thư mục của tôi, chứa không gian. Điều đó đòi hỏi một chút xử lý khác nhau của lệnh find.

  • Kịch bản gốc chỉ hoạt động cho các phần mở rộng chữ thường. Tôi đã cải thiện một chút phần kịch bản đó để giải thích cho các phần mở rộng được viết hoa. Lưu ý rằng nó chỉ chấp nhận DNG+JPGhoặc dng+jpgcặp và nó sẽ bỏ qua mọi kết hợp như DNG+jpghoặc DnG+JpG.

  • Giải pháp ban đầu chỉ đề xuất một wastedirvị trí, trong khi sửa lỗi của tôi cho phép tạo thư mục con trên mỗi nhánh thư mục khi nó di chuyển. Bạn xác định tên của thư mục trước vòng lặp.

  • Tôi muốn xem những gì đang xảy ra, đặc biệt là khi mvhoặc rmcác lệnh được sử dụng;)

Vì lợi ích của không gian Tôi chỉ hiển thị phần cuối của kịch bản, từ cách thiết lập một basedir, wastedirvà vòng lặp.

[...]

#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

Câu hỏi đã được gắn thẻ "windows" để bạn có thể làm với việc nói làm thế nào điều này có thể được thực hiện để hoạt động trong một hệ thống Windows điển hình. Tôi điều hành Cygwin, ví dụ (và tôi dự định sẽ có cái nhìn rõ hơn về câu trả lời này khi tôi ở trên máy tính để bàn, để thay đổi hành vi một chút)
Chris H

2

Đây là một giải pháp cho bash(Linux hoặc Mac OS X). Trên Windows, bạn có thể cài đặt Cygwin để lấy bản sao 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

Đây là một bashphiên bản khác sử dụng find(Linux). Như với câu trả lời của Ben Pingilley , bạn có thể cài đặt Cygwin để nhận bash trên 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

Đây là của tôi về vấn đề này. Rất nhiều ý tưởng hay đến từ các kịch bản trước đó được đề cập ở đây.

Đây là một kịch bản bash cho OS X . Nó tìm kiếm các tệp tồn tại với cùng tên tệp cơ sở và dng+jpgphần mở rộng. Nếu a jpgđược tìm thấy có cùng tên chính xác dng, thì tên tệp đó được hiển thị ( -e), tệp được di chuyển ( -m) hoặc bị xóa ( -d).

Nó sẽ đi qua các thư mục con, vì vậy bạn có thể sử dụng nó cho toàn bộ danh mục của bạn hoặc chỉ một phần của nó.

Đối với các phần mở rộng tệp thô khác, chỉ cần thay thế *.dngtrong tập lệnh bằng phần mở rộng ưa thích của bạn.

Cảnh báo: Bạn có thể có hai hình ảnh khác nhau có cùng tên, nhưng phần mở rộng khác nhau. Đó là những thương vong không thể tránh khỏi của kịch bản này.

Đây là cách sử dụng tập lệnh:

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 

Sử dụng cơ bản sẽ hoạt động như thế này:

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

Điều đó sẽ lặp lại tất cả tên tệp của jpgcác tệp phù hợp với tiêu chí có cả hai dngjpgtệp có cùng tên.

Kết quả sẽ trông giống như thế này:

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.

Bây giờ nếu tôi muốn xóa các tập tin, tôi sẽ chuyển -esang -d:

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

Hoặc nếu tôi muốn di chuyển các tệp đến / trùng lặp, tôi sẽ thực hiện nó với -m.

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

Bây giờ các jpgtệp trùng lặp sẽ ở trong/Volumes/photo/DNG/2015/duplicates

Đây là kịch bản: 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

Dưới đây là một bashkịch bản cho Mac OS X . Nó có thể hoạt động trên Linux với một số thay đổi.

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

rmtrashlà một tiện ích di chuyển các tệp vào Thùng rác, thay vì xóa chúng hoàn toàn. Bạn có thể lấy nó từ MacPorts:

sudo port install rmtrash

Nếu bạn muốn tránh điều đó, chỉ cần thay thế rmtrashtrong tập lệnh rm, nó sẽ xóa ngay các JPGtập tin.


1

Tôi đã viết kịch bản Python sau đây . So với kịch bản của ttaveira , nó thực hiện một số công việc phụ.

  • Nhìn trong thư mục con.
  • Tạo thư mục chất thải đích.
  • Loại bỏ các tập tin đã tồn tại trong thư mục chất thải để tránh lỗi di chuyển.

# 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
Xin chào và chào mừng đến với Photo.SE. Câu trả lời của bạn khác với câu trả lời của ttaveira như thế nào?
Saaru Lindestøkke

Kịch bản thực hiện một số công việc bổ sung: cũng tìm trong tất cả các thư mục con, tạo thư mục lãng phí đích cho jpg nếu nó không tồn tại và nó sẽ loại bỏ jpg thay vì di chuyển nếu nó đã tồn tại trong thư mục thải (tránh lỗi di chuyển)
Tomy

0

Làm việc trên Mac OS X , tôi đã thiếu kiểm tra độ tỉnh táo cho "cùng một nội dung" trong các câu trả lời trước. Tôi đã đặt tên trùng lặp cho các hình ảnh khác nhau vì tôi đã quên bật bộ đếm hình ảnh trong máy ảnh của mình. Đây là phiên bản của tôi, kiểm tra thông tin EXIF ​​trong cùng thời gian chụp:

Bạn cần phải chạy

sudo port install rmtrash exiv2

trước khi bạn có thể sử dụng lệnh sau. Nó được viết để so sánh JPGvới NEFcác tập tin từ chiếc Nikon D90 của tôi. Điều chỉnh các phần mở rộng tập tin theo nhu cầu của bạn.

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

không có sự kiểm tra về sự tỉnh táo, toàn bộ sự việc sẽ trở thành một lớp lót rất ngắn:

find . -name \*.NEF |sed s/\.NEF/.JPG/g | xargs find 2>/dev/null | xargs rmtrash
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.