Поиск и удаление дубликатов файлов в OSX с помощью скрипта

Поиск и удаление дубликатов файлов в OSX с помощью скрипта

От:http://www.chriswrites.com/2012/02/как-найти-и-удалить-дубликаты-файлов-в-mac-os-x/ Как мне изменить это так, чтобы удалить только первую версию файла, которую он видит?

Откройте Терминал из Spotlight или папки Utilities. Измените каталог (папку), в которой вы хотите выполнить поиск (включая подпапки), используя команду cd. В командной строке введите cd, например, cd ~/Documents, чтобы изменить каталог на домашнюю папку Documents. В командной строке введите следующую команду:

find . -size 20 \! -type d -exec cksum {} \; | sort | tee /tmp/f.tmp | cut -f 1,2 -d ' ' | uniq -d | grep -hif – /tmp/f.tmp > duplicates.txt

Этот метод использует простую контрольную сумму для определения идентичности файлов. Имена дубликатов будут перечислены в файле с именем duplicates.txt в текущем каталоге. Откройте его, чтобы просмотреть имена идентичных файлов. Теперь есть различные способы удаления дубликатов. Чтобы удалить все файлы в текстовом файле, в командной строке введите:

while read file; do rm "$file"; done < duplicates.txt

решение1

Во-первых, вам придется изменить порядок первой командной строки, чтобы сохранить порядок файлов, найденных командой find:

find . -size 20 ! -type d -exec cksum {} \; | tee /tmp/f.tmp | cut -f 1,2 -d ‘ ‘ | sort | uniq -d | grep -hif – /tmp/f.tmp > duplicates.txt

(Примечание: для тестирования на моей машине я использовал find . -type f -exec cksum {} \;)

Во-вторых, один из способов распечатать все, кроме первого дубликата, — это использовать вспомогательный файл, скажем /tmp/f2.tmp. Тогда мы могли бы сделать что-то вроде:

while read line; do
    checksum=$(echo "$line" | cut -f 1,2 -d' ')
    file=$(echo "$line" | cut -f 3 -d' ')

    if grep "$checksum" /tmp/f2.tmp > /dev/null; then
        # /tmp/f2.tmp already contains the checksum
        # print the file name
        # (printf is safer than echo, when for example "$file" starts with "-")
        printf %s\\n "$file"
    else
        echo "$checksum" >> /tmp/f2.tmp
    fi
done < duplicates.txt

Просто убедитесь, что он /tmp/f2.tmpсуществует и пуст, прежде чем запускать его, например, с помощью следующих команд:

rm /tmp/f2.tmp
touch /tmp/f2.tmp

Надеюсь, это поможет =)

решение2

Другой вариант — использовать fdupes:

brew install fdupes
fdupes -r .

fdupes -r .находит дубликаты файлов рекурсивно в текущем каталоге. Добавьте, -dчтобы удалить дубликаты — вам будет предложено, какие файлы сохранить; если вместо этого вы добавите -dN, fdupes всегда будет сохранять первый файл и удалять остальные файлы.

решение3

Я написал скрипт, который переименовывает ваши файлы в соответствии с хешем их содержимого.

Он использует подмножество байтов файла, поэтому работает быстро, а в случае коллизии добавляет к имени счетчик, например:

3101ace8db9f.jpg
3101ace8db9f (1).jpg
3101ace8db9f (2).jpg

Это позволяет легко просматривать и удалять дубликаты самостоятельно, не доверяя чужому программному обеспечению свои фотографии больше, чем это необходимо.

Сценарий: https://gist.github.com/SimplGy/75bb4fd26a12d4f16da6df1c4e506562

введите описание изображения здесь

решение4

Это делается с помощью приложения EagleFiler, разработанногоМайкл Цай.

tell application "EagleFiler"

      set _checksums to {}
      set _recordsSeen to {}
      set _records to selected records of browser window 1
      set _trash to trash of document of browser window 1
      repeat with _record in _records
          set _checksum to _record's checksum
          set _matches to my findMatch(_checksum, _checksums, _recordsSeen)
          if _matches is {} then
              set _checksums to {_checksum} & _checksums
              set _recordsSeen to {_record} & _recordsSeen
          else
              set _otherRecord to item 1 of _matches
              if _otherRecord's modification date > _record's modification date 
then

            set _record's container to _trash
            else
                set _otherRecord's container to _trash
                set _checksums to {_checksum} & _checksums
                set _recordsSeen to {_record} & _recordsSeen
            end if
        end if
    end repeat
end tell

on findMatch(_checksum, _checksums, _recordsSeen)

    tell application "EagleFiler"
        if _checksum is "" then return {}
        if _checksums contains _checksum then
            repeat with i from 1 to length of _checksums
                if item i of _checksums is _checksum then
                    return item i of _recordsSeen
                end if
            end repeat
        end if
        return {}
    end tell

end findMatch

Вы также можете автоматически удалять дубликаты с помощью средства удаления дубликатов файлов, предложенного вэта почта.

Связанный контент