Искать дубликаты имен файлов в иерархии папок?


29

У меня есть папка с именем img, эта папка имеет много уровней подпапок, все из которых содержат изображения. Я собираюсь импортировать их в сервер изображений.

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

Например изображения background.pngи background.gifне будут разрешены, потому что, даже если они имеют разные расширения, они по-прежнему имеют одинаковое имя файла. Даже если они находятся в отдельных подпапках, они все равно должны быть уникальными.

Поэтому мне интересно, могу ли я выполнить рекурсивный поиск в imgпапке, чтобы найти список файлов с одинаковым именем (исключая расширение).

Есть команда, которая может сделать это?


@DavidFoerster Ты прав! Я понятия не имею, почему я подумал, что это может быть дубликатом Как найти (и удалить) дубликаты файлов , но, очевидно, это не так.
Элия ​​Каган

Ответы:


17

FSlint Установить fslint - это универсальный инструмент поиска дубликатов, который включает функцию поиска дубликатов имен:

FSlint

Пакет FSlint для Ubuntu подчеркивает графический интерфейс, но, как объясняется в FAQ по FSlint, интерфейс командной строки доступен через программы в /usr/share/fslint/fslint/. Используйте --helpопцию для документации, например:

$ /usr/share/fslint/fslint/fslint --help
File system lint.
A collection of utilities to find lint on a filesystem.
To get more info on each utility run 'util --help'.

findup -- find DUPlicate files
findnl -- find Name Lint (problems with filenames)
findu8 -- find filenames with invalid utf8 encoding
findbl -- find Bad Links (various problems with symlinks)
findsn -- find Same Name (problems with clashing names)
finded -- find Empty Directories
findid -- find files with dead user IDs
findns -- find Non Stripped executables
findrs -- find Redundant Whitespace in files
findtf -- find Temporary Files
findul -- find possibly Unused Libraries
zipdir -- Reclaim wasted space in ext2 directory entries
$ /usr/share/fslint/fslint/findsn --help
find (files) with duplicate or conflicting names.
Usage: findsn [-A -c -C] [[-r] [-f] paths(s) ...]

If no arguments are supplied the $PATH is searched for any redundant
or conflicting files.

-A reports all aliases (soft and hard links) to files.
If no path(s) specified then the $PATH is searched.

If only path(s) specified then they are checked for duplicate named
files. You can qualify this with -C to ignore case in this search.
Qualifying with -c is more restictive as only files (or directories)
in the same directory whose names differ only in case are reported.
I.E. -c will flag files & directories that will conflict if transfered
to a case insensitive file system. Note if -c or -C specified and
no path(s) specifed the current directory is assumed.

Пример использования:

$ /usr/share/fslint/fslint/findsn /usr/share/icons/ > icons-with-duplicate-names.txt
$ head icons-with-duplicate-names.txt 
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity-Dark/AUTHORS
-rw-r--r-- 1 root root    683 2011-04-15 10:31 Humanity/AUTHORS
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity-Dark/COPYING
-rw-r--r-- 1 root root  17992 2011-04-15 10:31 Humanity/COPYING
-rw-r--r-- 1 root root   4776 2011-03-29 08:57 Faenza/apps/16/DC++.xpm
-rw-r--r-- 1 root root   3816 2011-03-29 08:57 Faenza/apps/22/DC++.xpm
-rw-r--r-- 1 root root   4008 2011-03-29 08:57 Faenza/apps/24/DC++.xpm
-rw-r--r-- 1 root root   4456 2011-03-29 08:57 Faenza/apps/32/DC++.xpm
-rw-r--r-- 1 root root   7336 2011-03-29 08:57 Faenza/apps/48/DC++.xpm
-rw-r--r-- 1 root root    918 2011-03-29 09:03 Faenza/apps/16/Thunar.png

Спасибо, это сработало. Некоторые результаты выделены фиолетовым, а некоторые - зеленым. Вы знаете, что означают разные цвета?
Джей Ди Айзекс

@John Похоже, что FSlint использует ls -lдля форматирования своего вывода. Этот вопрос должен объяснить, что означают цвета.
rndrük

FSlint имеет много зависимостей.
Навин

31
find . -mindepth 1 -printf '%h %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | tr ' ' '/'

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

find . -mindepth 1 -type f -printf '%p %f\n' | sort -t ' ' -k 2,2 | uniq -f 1 --all-repeated=separate | cut -d' ' -f1

Я изменил решение так, чтобы оно возвращало полный (относительный) путь всех дубликатов. К сожалению, предполагается, что имена путей не содержат пробелов, поскольку uniqне предоставляют возможности выбора другого разделителя полей.
Дэвид Фёрстер

@DavidFoerster, ваша версия 6 была улучшением, но что касается вашего комментария, с каких пор он sedустарел? Arcane? Конечно. Вышло из употребления? Не то, чтобы я знал. (И я просто искал, чтобы проверить.)
cp.engr

@ cp.engr: sed не устарел. Его вызов устарел после очередной моей смены.
Дэвид Фёрстер

@DavidFoerster, устаревшее не кажется мне подходящим словом. Я думаю, что «устраненный» будет лучше подойдет. В любом случае, спасибо за разъяснения.
cp.engr

@ cp.engr: Спасибо за предложение! Я не знал этого слова, но, похоже, оно лучше соответствует ситуации.
Дэвид Фёрстер

8

Сохраните это в файл с именем duplicates.py

#!/usr/bin/env python

# Syntax: duplicates.py DIRECTORY

import os, sys

top = sys.argv[1]
d = {}

for root, dirs, files in os.walk(top, topdown=False):
    for name in files:
        fn = os.path.join(root, name)
        basename, extension = os.path.splitext(name)

        basename = basename.lower() # ignore case

        if basename in d:
            print(d[basename])
            print(fn)
        else:
            d[basename] = fn

Затем сделайте файл исполняемым:

chmod +x duplicates.py

Запустите, например, так:

./duplicates.py ~/images

Он должен выводить пары файлов с одинаковым базовым именем (1). Написанный на Python, вы должны быть в состоянии изменить его.


Кажется, это не работает должным образом. Он обнаруживает P001.ORFи P001 (1).ORFкак дубликаты, а также кажется, что 60% моих файлов являются дубликатами, что я не уверен, я уверен. fslintнашел реальное количество повторяющихся имен файлов, которое близко к 3%.
Рольф

3

Я предполагаю, что вам нужно только увидеть эти «дубликаты», а затем обработать их вручную. Если так, то этот код bash4 должен делать то, что вы хотите, я думаю.

declare -A array=() dupes=()
while IFS= read -r -d '' file; do 
    base=${file##*/} base=${base%.*}
    if [[ ${array[$base]} ]]; then 
        dupes[$base]+=" $file"
    else
        array[$base]=$file
    fi
done < <(find /the/dir -type f -print0)

for key in "${!dupes[@]}"; do 
    echo "$key: ${array[$key]}${dupes[$key]}"
done

См. Http://mywiki.wooledge.org/BashGuide/Arrays#Associative_Arrays и / или руководство по bash для получения справки по синтаксису ассоциативного массива.


Как мне выполнить такую ​​команду в терминале? Это то, что мне нужно сначала сохранить в файл и выполнить файл?
JD Исаакс

@John Isaacks Вы можете скопировать / вставить его в терминал или поместить в файл и запустить как скрипт. Любой случай достигнет того же самого.
гейра

1

Это bname:

#!/bin/bash
#
#  find for jpg/png/gif more files of same basename 
#
# echo "processing ($1) $2"
bname=$(basename "$1" .$2)
find -name "$bname.jpg" -or -name "$bname.png"

Сделайте его исполняемым:

chmod a+x bname 

Вызвать это:

for ext in jpg png jpeg gif tiff; do find -name "*.$ext" -exec ./bname "{}" $ext ";"  ; done

Pro:

  • Это просто и просто, поэтому расширяемо.
  • Обрабатывает пробелы, вкладки, переносы строк и переходы в именах файлов, afaik. (Предполагая, что нет такой вещи в добавочном имени).

Против:

  • Он всегда находит сам файл, и если он находит a.gif для a.jpg, он также находит a.jpg для a.gif. Таким образом, для 10 файлов с одинаковым базовым именем он находит 100 совпадений в конце.

0

Улучшение скрипта loevborg, для моих нужд (включает сгруппированный вывод, черный список, более чистый вывод при сканировании). Я сканировал диск на 10 ТБ, поэтому мне нужно было немного чище.

Использование:

python duplicates.py DIRNAME

duplicates.py

    #!/usr/bin/env python

    # Syntax: duplicates.py DIRECTORY

    import os
    import sys

    top = sys.argv[1]
    d = {}

    file_count = 0

    BLACKLIST = [".DS_Store", ]

    for root, dirs, files in os.walk(top, topdown=False):
        for name in files:
            file_count += 1
            fn = os.path.join(root, name)
            basename, extension = os.path.splitext(name)

            # Enable this if you want to ignore case.
            # basename = basename.lower()

            if basename not in BLACKLIST:
                sys.stdout.write(
                    "Scanning... %s files scanned.  Currently looking at ...%s/\r" %
                    (file_count, root[-50:])
                )

                if basename in d:
                    d[basename].append(fn)
                else:
                    d[basename] = [fn, ]

    print("\nDone scanning. Here are the duplicates found: ")

    for k, v in d.items():
        if len(v) > 1:
            print("%s (%s):" % (k, len(v)))
            for f in v:
                print (f)
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.