Есть ли способ удалить дубликаты, более совершенные, чем fdupes -rdN?

Недавно мне нужно удалить много дубликатов. Я объединяю три или четыре файловые системы, и я хочу, чтобы пространство использовалось экономически. Сначала fdupes показалось, что это лучший инструмент для работы, но я все чаще сталкиваюсь с ограничениями.

Рассмотрим команду fdupes -rdN somedirectory/ . Это делает хэш всех файлов в подкаталогах somedirectory.

  • Unix - как извлекать файлы на основе части имени файла, которая является датой
  • Заменяйте строки, соответствующие шаблону, строками из другого файла в порядке
  • Автоматическое перемещение файлов в каталог один за другим и только тогда, когда целевая папка пуста
  • Использование GNU Parallel With Split
  • В какую файловую систему включен мой файл?
  • Защищать журнал сеанса от записи другим пользователем
  • И когда он сталкивается с дубликатами, он удаляет их, так что есть только одна копия всего.

    Но что, если я хочу сохранить somedirectory/subdirectory1/somefile и есть, по сути, четыре дубликата, и программа сначала встречает один из дубликатов? Затем он удаляет somedirectory/subdirectory1/somefile , чего я не хочу.

    Я хочу иметь возможность указать, каким-то образом дублировать, чтобы сохранить. И до сих пор ни одна из стандартных программ для работы с дубликатами (duff, FSLint), похоже, не позволяет автоматизировать такое поведение. Я бы предпочел не сворачивать себя, поэтому я задаю этот вопрос.

    Я хотел бы написать что-то вроде

     killdupes -rdN --keep=filesin,somedirectories,separated,by,commas somedirectory/ 

  • Содержимое файла, созданное при открытии
  • В виртуальной виртуальной машине как установить права доступа к файловой системе?
  • Как создать списки прав на папки для каждого пользователя?
  • Сортировка файлов с определенным расширением с измененным временем и сохранение их в массив
  • Как установить программу EMIRGE для записи файлов с требуемым разрешением
  • Переименуйте кучу файлов с определенным шаблоном
  • 7 Solutions collect form web for “Есть ли способ удалить дубликаты, более совершенные, чем fdupes -rdN?”

    Как связать дублирующиеся файлы вместе? Таким образом, пространство используется только один раз, но они все еще существуют во всех путях. Уловка заключается в том, что файлы с жесткой привязкой должны быть изменены на месте (их нужно только изменить, удалив файл и воссоздав его с новым контентом). Другой подход состоит в том, чтобы символизировать файлы вместе, хотя у вас есть одна и та же проблема с решением, какой именно «первичный» файл. Это можно сделать со следующим скриптом (хотя обратите внимание, что это не обрабатывает имена файлов, содержащие пробелы).

     fdupes --quiet --recurse --sameline somedirectory/ | while read SOURCE DESTS; do for DEST in $DESTS; do ln -f $SOURCE $DEST done done 

    Я не видел этого в другом месте: Скажи, что ты хочешь, это так. У вас есть / mnt / folder-tree-1 / mnt / folder-tree-2. Вы не хотите удалять все обманы, но если файл существует в tree-2, а идентичный файл существует в tree-1 с тем же самым путем и именем, удалите его из дерева-2.

    Предупреждение: это довольно краткий, и если вы попытаетесь скопировать его с ограниченными навыками оболочки, будьте осторожны.

     fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line do if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt then echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2//|')\" fi done > rm-v2-dupes.sh 

    Или все на одной линии:

     fdupes -rn /mnt/folder-tree-1/ /mnt/folder-tree-2/ > dupes-all.txt; fgrep /mnt/folder-tree-1/ dupes-all.txt | while read line; do if grep -q "`echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|'`" dupes-all.txt; then echo rm \"$(echo $line | sed -e 's|^/mnt/folder-tree-1/|/mnt/folder-tree-2/|')\"; fi; done > rm-v2-dupes.sh 

    Затем проверьте и выполните rm-v2-dupes.sh

    Используйте sed для создания файла оболочки, который будет содержать команды с комментариями для удаления каждого из ваших дубликатов файлов:

     fdupes -r -n -S /directory | sed -r "s/^/#rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh 

    В результате remove-duplicate-files.sh файла remove-duplicate-files.sh который мы только что создали, будет выведена каждая строка. Раскомментируйте файлы, которые хотите удалить. Затем запустите sh remove-duplicate-files.sh . Вуаля!

    ОБНОВИТЬ

    Ну, если вы не хотите удалять файлы только в определенных каталогах, это так просто :

     fdupes -S /directory|sed '/^$/d' |sed -r "s/^[0-9]/#&/" > duple_list python exclude_duplicates.py -f /path/to/dupe_list --delimiter='#' --keep=/full/path/to/protected/directory1,/full/path/to/protected/directory2\ with\ spaces\ in\ path >remove-duplicate-files-keep-protected.sh 

    Где exclude_duplicates.py :

     #/usr/bin/python # -*- coding: utf-8 -*- # exclude_duplicates.py """ THE SCRIPT DOESN'T DELETE ANYTHING, IT ONLY GENERATES TEXT OUTPUT. Provided a list of duplicates, such as fdupes or fslint output, generate a bash script that will have all duplicates in protected directories commented out. If none of the protected duplicates are found in a set of the same files, select a random unprotected duplicate for preserving. Each path to a file will be transformed to an `rm "path"` string which will be printed to standard output. """ from optparse import OptionParser parser = OptionParser() parser.add_option("-k", "--keep", dest="keep", help="""List of directories which you want to keep, separated by commas. \ EXAMPLE: exclude_duplicates.py --keep /path/to/directory1,/path/to/directory\ with\ space\ in\ path2""", metavar="keep" ) parser.add_option("-d", "--delimiter", dest="delimiter", help="Delimiter of duplicate file groups", metavar="delimiter" ) parser.add_option("-f", "--file", dest="file", help="List of duplicate file groups, separated by delimiter, for example, fdupes or fslint output.", metavar="file" ) (options, args) = parser.parse_args() directories_to_keep = options.keep.split(',') file = options.file delimiter = options.delimiter pretty_line = '\n#' + '-' * 35 print '#/bin/bash' print '#I will protect files in these directories:\n' for d in directories_to_keep: print '# ' + d print pretty_line protected_set = set() group_set = set() def clean_set(group_set, protected_set, delimiter_line): not_protected_set = group_set - protected_set while not_protected_set: if len(not_protected_set) == 1 and len(protected_set) == 0: print '#randomly selected duplicate to keep:\n#rm "%s"' % not_protected_set.pop().strip('\n') else: print 'rm "%s"' % not_protected_set.pop().strip('\n') for i in protected_set: print '#excluded file in protected directory:\n#rm "%s"' % i.strip('\n') print '\n#%s' % delimiter_line file = open(file, 'r') for line in file.readlines(): if line.startswith(delimiter): clean_set(group_set, protected_set, line) group_set, protected_set = set(), set() else: group_set = group_set|{line} for d in directories_to_keep: if line.startswith(d): protected_set = protected_set|{line} else: if line: clean_set(group_set, protected_set, line) 

    В результате remove-duplicate-files-keep-protected.sh файла remove-duplicate-files-keep-protected.sh который мы только что создали, будут remove-duplicate-files-keep-protected.sh все файлы из защищенных каталогов. Откройте этот файл в своем любимом текстовом редакторе, убедитесь, что все в порядке. Затем запустите его. Voila (sic)!

    Как насчет чего-то подобного?

     #!/bin/bash DUPE_SEARCH_DIR=somedir/ PREFERRED_DIRS=("somedir/subdir1" "somedir/subdir2") DUPE_FILE=/tmp/`basename $0`_found-duplicates delete_dupes() { while read line ; do if [ -n "$line" ] ; then matched=false for pdir in "${PREFERRED_DIRS[@]}" ; do if [[ $line == $pdir/* ]] ; then matched=true break fi done if ! $matched ; then rm -v "$line" fi fi done < "$DUPE_FILE" } cleanup() { rm -f $DUPE_FILE } trap cleanup EXIT # get rid of normal dupes, preserve first & preserve preferred fdupes -rf "$DUPE_SEARCH_DIR" > $DUPE_FILE delete_dupes # get rid of preserve dupes, preserve preferred fdupes -r "$DUPE_SEARCH_DIR" > "$DUPE_FILE" delete_dupes 

    У меня такой же вопрос. Если у вас много дубликатов, fdupes -rdN сохраняет файл с самой старой датой изменения, или если несколько файлов имеют одну и ту же дату изменения, то первая найдена.

    Если дата изменения не важна для вас, вы можете touch файлов в каталоге, который хотите сохранить. Если вы решите touch их текущей датой и временем, то fdupes -rdNi сохранит их с текущей датой. Или вы можете touch к файлам сохранения с датой раньше, чем даты тех, которые хотите удалить, и использовать fdupes -rdN как обычно.

    Если вам нужно сохранить дату изменения, вам нужно будет использовать один из других методов.

    Просто добавьте твист к предыдущему ответу. Я использовал следующий код несколько раз, слегка изменив предыдущий ответ с помощью простого | grep | grep чтобы изолировать папку, которую я хочу удалить.

     `fdupes -r -n -S /directory | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh` 

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

    Еще один намек на большие каталоги – запустить fdupes в txt-файл, а затем поэкспериментировать с | grep | grep и | sed | sed пока я не получу результат, который я хочу.

     `fdupes -r -n -S /directory > duplicate-files.txt` `cat duplicate-files.txt | grep /delete-from-directory | sed -r "s/^/rm \"/" | sed -r "s/$/\"/" >remove-duplicate-files.sh` 

    Хотя функциональность, которую вы ищете, недоступна в запасе fdupes , я fdupes (моя вилка называется jdupes ) и добавила некоторые функции, которые могут решить эту проблему при определенных обстоятельствах. Например, в заявленном случае, когда вы хотите сохранить somedirectory/subdirectory1/somefile при автоматическом удалении дубликатов ( d и N переключаются вместе), и нет сразу отдельных файлов под somedirectory , jdupes может быть jdupes каждый непосредственный путь subdirectory1 с помощью subdirectory1 сначала и -O (который сортирует файлы по порядку параметров командной строки):

    jdupes -nrdNO somedirectory/subdirectory1 somedirectory/subdirectory2 somedirectory/subdirectory3

    Это автоматически удалит все, кроме одного файла, в дубликатном наборе и будет гарантировать, что если набор содержит файл в somedirectory/subdirectory1 он будет первым, тем самым автоматически станет сохраненным файлом в наборе. До сих пор существуют все более очевидные ограничения для такого подхода, такие как тот факт, что другой дубликат в somedirectory/subdirectory1 может быть сохранен вместо того, который вы хотите сохранить, но в jdupes количестве случаев, подобных вашей, параметр порядка параметров jdupes в качестве обходного пути достаточно хорошо.

    В ближайшем будущем я планирую добавить фильтрующую систему в jdupes , которая позволит контролировать объем включения / исключения файлов, сохранение для -N действий и применение таких «стеков фильтров» на глобальном или пер- параметр. Эта функция очень необходима; Я предвижу что-то вроде этого: «автоматически удалять ненулевые дубликаты рекурсивно, но всегда somedirectory/subdirectory1/somefile as-is»:

    jdupes -nrdN --filter=preserve:somedirectory/subdirectory1/somefile somedirectory/

    Linux и Unix - лучшая ОС в мире.