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

11

От: http://www.chriswrites.com/2012/02/how-to-find-and-delete-duplicate-files-in-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
сойка
источник

Ответы:

4

Во-первых, вам нужно изменить порядок первой командной строки, чтобы сохранить порядок файлов, найденных командой 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

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

Джанито Вакейру Феррейра Филю
источник
39

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

brew install fdupes
fdupes -r .

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

LRI
источник
7
fdupesявляется удивительным! Работал как шарм! Спасибо брат.!
racl101
3

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

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

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

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

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

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

SimplGy
источник
+1 только для GIF-дисплея !!
NoobEditor
0

Это делается с помощью приложения 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

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

Dejise
источник
1
(1) Что такое «EagleFiler»? Это часть macOS? Если нет, где ты это взял? (2) Это должен быть один длинный блок кода (как я это исправил)? (3) Пожалуйста, исправьте свой отступ. (4) Как именно это можно использовать?
Скотт