
От: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
Вы также можете автоматически удалять дубликаты с помощью средства удаления дубликатов файлов, предложенного вэта почта.