У меня есть два каталога, они содержат общие файлы. Я хочу знать, содержит ли один каталог тот же файл как другой. Я нашел сценарий в сети, но я хочу должен улучшить ее, чтобы сделать рекурсивно.
#!/bin/bash
# cmp_dir - program to compare two directories
# Check for required arguments
if [ $# -ne 2 ]; then
echo "usage: $0 directory_1 directory_2" 1>&2
exit 1
fi
# Make sure both arguments are directories
if [ ! -d $1 ]; then
echo "$1 is not a directory!" 1>&2
exit 1
fi
if [ ! -d $2 ]; then
echo "$2 is not a directory!" 1>&2
exit 1
fi
# Process each file in directory_1, comparing it to directory_2
missing=0
for filename in $1/*; do
fn=$(basename "$filename")
if [ -f "$filename" ]; then
if [ ! -f "$2/$fn" ]; then
echo "$fn is missing from $2"
missing=$((missing + 1))
fi
fi
done
echo "$missing files missing"
Кто-либо предложил бы алгоритм для него?
#!/bin/bash
# cmp_dir - program to compare two directories
# Check for required arguments
if [ $# -ne 2 ]; then
echo "usage: $0 directory_1 directory_2" 1>&2
exit 1
fi
# Make sure both arguments are directories
if [ ! -d "$1" ]; then
echo "$1 is not a directory!" 1>&2
exit 1
fi
if [ ! -d "$2" ]; then
echo "$2 is not a directory!" 1>&2
exit 1
fi
# Process each file in directory_1, comparing it to directory_2
missing=0
while IFS= read -r -d $'\0' filename
do
fn=${filename#$1}
if [ ! -f "$2/$fn" ]; then
echo "$fn is missing from $2"
missing=$((missing + 1))
fi
done < <(find "$1" -type f -print0)
echo "$missing files missing"
Обратите внимание, что я добавил двойные кавычки вокруг $1
и $2
в различных местах выше для защиты их окружают расширение. Без двойных кавычек имена каталогов с пробелами или другими трудными символами вызвали бы ошибки.
Ключевой цикл теперь читает:
while IFS= read -r -d $'\0' filename
do
fn=${filename#$1}
if [ ! -f "$2/$fn" ]; then
echo "$fn is missing from $2"
missing=$((missing + 1))
fi
done < <(find "$1" -type f -print0)
Это использует find
рекурсивно погружаться в каталог $1
и найдите имена файлов. Конструкция while IFS= read -r -d $'\0' filename; do .... done < <(find "$1" -type f -print0)
безопасно против всех имен файлов.
basename
больше не используется, потому что мы смотрим на файлы в подкаталогах, и мы должны сохранить подкаталоги. Так, вместо вызова к basename
, строка fn=${filename#$1}
используется. Это просто удаляет из filename
префикс, содержащий каталог $1
.
Предположим, что мы соответствуем файлам по имени, но независимо от каталога. Другими словами, если первый каталог содержит файл a/b/c/some.txt
, мы будем считать это существующим во втором каталоге если файл some.txt
существует в любом подкаталоге второго каталога. Сделать эту замену цикл выше с:
while IFS= read -r -d $'\0' filename
do
fn=$(basename "$filename")
if ! find "$2" -name "$fn" | grep -q . ; then
echo "$fn is missing from $2"
missing=$((missing + 1))
fi
done < <(find "$1" -type f -print0)
FSlint является маленьким приложением GUI, которое помогает Вам определить и убрать свою систему избыточных файлов.
Установка FSlint
Установите FSlint от Центра программного обеспечения Ubuntu, или из командной строки следующим образом:
sudo apt-get install fslint
(В моей системе, устанавливая FSlint не вытягивал в дополнительных зависимостях. А именно, fslint зависит от findutils, Python и python-glade2, который уже должен все быть в Вашей системе. Можно удалить FSlint использование Центра программного обеспечения или путем ввода sudo apt-get autoremove --purge fslint
в терминале).
Поиск файлов
Запустите FSlint от тире единицы.
Вот снимок экрана основного экрана. Существует много расширенных функций, но основное использование приложения относительно просто.
Нажмите Add
кнопка наверху уехала для добавления всех каталогов, которые требуется проверить. Очевидно, можно удалить каталоги с помощью Remove
кнопка.
Удостоверьтесь recurse?
флажок в право устанавливается. Затем нажмите Find
кнопка. (Любые ошибки, такие как разрешение файла проблемы, будут распечатаны у основания окна FSlint).
FSlint перечислит все дубликаты файлов, их местоположения каталога и дату файла. FSlint также дарит Вам число байтов, потраченных впустую из-за избыточных файлов.
Удаление дубликатов
Теперь можно выбрать несколько файлов с помощью клавиш Shift или клавиш Ctrl и левой кнопки мыши. Если Вы хотите выбрать несколько файлов автоматически, нажмите Select
кнопке и Вам дадут опции, такие как выбор файлов на основе даты или ввода подстановочных критериев выбора.
Если необходимо использовать список выбранных файлов за пределами FSlint (возможно, как введено к собственному сценарию), нажимают Save
кнопка для сохранения текстового файла.
Наконец можно удалить выбранные файлы с помощью Delete
кнопка, или можно объединить выбранные файлы с помощью Merge
кнопка. Обратите внимание что Merge
функция удаляет отмененные выбор файлы из Вашей системы и создает жесткие ссылки на соответствующие выбранные файлы. Вы использовали бы эту функцию, если бы Вы хотели сохранить свою существующую файловую структуру, но хотели освободить некоторое пространство в своей системе.
Дополнительные функции и Документация
FSlint имеет другие мощные функции, которые доступны от вкладок в левой панели. Я нашел Name clashes
чтобы быть полезным, где существуют файлы, которые имеют то же имя, но отличаются (возможно, потому что Вы сохранили более новую версию файла в другом каталоге).
Существует также Advanced search parameters
вкладка наверху окна FSlint, которое позволяет Вам исключать определенные каталоги в своем поиске или фильтровать Ваши результаты с помощью параметров.
Там ре много мощных функций в этом простом небольшом инструменте. Это может сохранить Вас усилие по необходимости записать и отладить сценарий. Можно узнать больше по http://www.pixelbeat.org/fslint/. Вот прямая ссылка на английское руководство: http://en.flossmanuals.net/fslint/.
Я хочу совместно использовать этот путь, потому что я думаю, что это довольно забавно.
Для каждой подпапки ниже целевой папки, мы генерируем хеш для той подпапки.
Каждый хеш папки сгенерирован от результата хеширования всех файлов ниже той папки. Таким образом, любая папка, содержащая идентичные файлы в той же структуре, должна произвести тот же хеш!
В конце, мы используем uniq
для отображения только дублирующихся хешей папки.
Сохраняют следующий сценарий как seek_duplicate_folders.sh
и затем выполняют его как это:
$ bash seek_duplicate_folders.sh [root_folder_to_scan]
Вот сценарий:
#!/bin/bash
target="$1"
hash_folder() {
echo "Hashing $1" >/dev/stderr
pushd "$1" >/dev/null
# Hash all the files
find . -type f | sort | xargs md5sum |
# Hash that list of hashes, discard the newline character,
# and append the folder name
md5sum - | tr -d '\n'
printf " %s\n" "$1"
popd >/dev/null
}
find "$target" -type d |
while read dir
do hash_folder "$dir"
done |
sort |
# Display only the lines with duplicate hashes (first 32 chars are duplicates)
uniq -D -w 32
Протесты: