Видео смотреть бесплатно

Смотреть кино видео

Официальный сайт aksakal 24/7/365

Смотреть видео бесплатно

18.01.10 23:27

digiwhiteСравнение двух директорий и удаление из второй файлов-дубликатов

Чего-то читая форумы, увидел, что некоторые ищут как удалить файлы-дубликаты (чаще это фотографии или музыка) из одного из двух каталогов. Поэтому, решил набросать скриптик на bash`е, который позволяет это делать.


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

Собственно далее идет код:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183

#!/bin/bash

PARAM_NUMBER=0
TMP_FILE_LIST_1=/tmp/dir_1.filelist
TMP_FILE_LIST_2=/tmp/dir_2.filelist
TMP_FILE_LIST_SUM_1=/tmp/dir_1.filelist.md5
TMP_FILE_LIST_SUM_2=/tmp/dir_2.filelist.md5
ME=`basename $0`
PRINT_ONLY=0


function print_help() {
        echo "Script compare two folder and remove duplicates from second."    
        echo
        echo "Usage: $ME [-f folder] [-s folder] <-p> | [-h]"
        echo "Parameters:"
        echo "  -f folder       First folder to compare."
        echo "  -s folder       Second folder to compare."
        echo "  -p              Only show duplicates which were found."
        echo "  -h              Print help screen."
        echo
}

function cleanup() {
        if [ -f $TMP_FILE_LIST_1 ] ; then
                rm -f $TMP_FILE_LIST_1
        fi

        if [ -f $TMP_FILE_LIST_2 ] ; then
                rm -f $TMP_FILE_LIST_2
        fi

        if [ -f $TMP_FILE_LIST_SUM_1    ] ; then
                rm -f $TMP_FILE_LIST_SUM_1
        fi

        if [ -f $TMP_FILE_LIST_SUM_2 ] ; then
                rm -f $TMP_FILE_LIST_SUM_2
        fi
}

if [ $# = 0 ] ; then
        print_help
        exit 3
fi

while getopts f:s:hp opt ;
do
        case $opt in
                f) DIR_1=$OPTARG;
                         let PARAM_NUMBER=$PARAM_NUMBER+1;
                         ;;
                s) DIR_2=$OPTARG;
                         let PARAM_NUMBER=$PARAM_NUMBER+1;
                         ;;
                h) print_help;
                         exit 3;
                         ;;
                p) let PRINT_ONLY=1
                         ;;
                *) echo "Bad script parameter";
                         exit 3
                         ;;
                esac
done

if [ $PARAM_NUMBER != 2 ] ; then
        echo "Wrong parameters number.";
        print_help
fi

if [ ! -d $DIR_1 ] ; then
        echo "Directory \"$DIR_1\" doesn\`t exists. Aborting!"
        exit 4
fi

if [ ! -d $DIR_2 ] ; then
        echo "Directory \"$DIR_2\" doesn\`
t exists. Aborting!"

        exit 4
fi


# Получаем список файлов (включая поддиректории) в директории 1
find $DIR_1 -type f | xargs | sort > $TMP_FILE_LIST_1

if [ ! -f $TMP_FILE_LIST_1 ] ; then
        echo "Can\`t get access to /tmp directory or can\`t create temporary file list. Aborting!"
        exit 5
fi


# Получаем список файлов (включая поддиректории) в директории 2
find $DIR_2 -type f | xargs | sort > $TMP_FILE_LIST_2

if [ ! -f $TMP_FILE_LIST_2 ] ; then
        cleanup
        echo "Can\`t get access to /tmp directory or can\`t create temporary file list. Aborting!"
        exit 5
fi


# Формируем список пар значений {хеш файла, имя файла} для директории 1
cat $TMP_FILE_LIST_1 | xargs md5sum > $TMP_FILE_LIST_SUM_1

if [ ! -f $TMP_FILE_LIST_SUM_1 ] ; then
        cleanup
        echo "Can\`t get access to /tmp directory or can\`t create temporary file list. Aborting!"
        exit 5
fi


# Формируем список пар значений {хеш файла, имя файла} для директории 2
cat $TMP_FILE_LIST_2 | xargs md5sum > $TMP_FILE_LIST_SUM_2

if [ ! -f $TMP_FILE_LIST_SUM_2 ] ; then
        cleanup
        echo "Can\`t get access to /tmp directory or can\`t create temporary file list. Aborting!"
        exit 5

fi

# Формируем списки для просмотра
FILE1=`cat $TMP_FILE_LIST_SUM_1 | xargs`
FILE2=`cat $TMP_FILE_LIST_SUM_2 | xargs`

REC_COUNTER_1=0
REC_COUNTER_2=0
SUM_1=
SUM_2=

# Поэлементно сравниваем два списка
for f in $FILE1 ; do
        if [ $REC_COUNTER_1 = 0 ] ; then
                SUM_1=$f
                SUM_1=`echo $SUM_1 | tr -d \"\\n\"`
                let REC_COUNTER_1=$REC_COUNTER_1+1
        else
                if [ $REC_COUNTER_1 = 1 ] ; then
                        FILE_NAME_1=$f
                        FILE_NAME_1=`echo $FILE_NAME_1 | tr -d \"\\n\"`
                       
                        for ff in $FILE2 ; do
                                if [ $REC_COUNTER_2 = 0 ] ; then
                                        SUM_2=$ff
                                        SUM_2=`echo $SUM_2 | tr -d \"\\n\"`
                                        let REC_COUNTER_2=$REC_COUNTER_2+1
                                else
                                        FILE_NAME_2=$ff
                                        FILE_NAME_2=`echo $FILE_NAME_2 | tr -d \"\\n\"`
                                        let REC_COUNTER_2=0

                                        # Если контрольные суммы совпадают, то удалить файл из директории 2
                                        # (если установлен параметр -p, то только вывести сообщение,
                                        # что найдены одинаковые файлы
                                        if [ "$SUM_1" = "$SUM_2" ] ; then
                                                echo "[=] Files \"$FILE_NAME_1\" and \"$FILE_NAME_2\" are equals".
                                               
                                                if [ $PRINT_ONLY = 0 ] ; then
                                                        echo "  [!] Deleting \"$FILE_NAME_2\""
                                                        rm -f $FILE_NAME_2
                                                fi
                                        fi

                                        SUM_2=
                                        FILE_NAME_2=
                                        let REC_COUNTER_2=0

                                fi

                        done
       
                        SUM_1=
                        FILE_NAME_1=

                        let REC_COUNTER_1=0
                fi
        fi
done

# Удалить временные файлы (файлы со списками)
cleanup
 


Суть работы скрипта достаточно проста и прозрачна.

В начале, мы проверяем количество параметров, что за параметры нам были переданы и совпало ли их количество. Далее проверяем, существуют ли указанные директории. Если директории существуют, то создаем два списка (по одному для каждой директории), содержащих пары {хеш значение файла(дайджест),имя файла}. Списки эти получаются в два этапа:
  1. создание отсортированного списка файлов (можно и не сортировать конечно);
  2. прохождение по списку файлов из пункт 1 и подсчет для каждого файла хеш-значения с помощью md5sum (можно так же использовать sha1sum, sha224sum, sha256sum и т.п.), и запись пары {хеш-значение, имя файла} в другой список.

Затем сравниваем оба списка поэлементно - каждый элемента списка файлов первой директории с каждым элементом списка файлов второй директории. Если элементы совпали, то из второй директории удаляем файл-дубликат. Когда сравнение списков завершается, то удаляем временные файлы, содержащие сами списки.

Как использовать:
./имя_скрипта -f ~/dir1 -s ~/dir2

Если в директории dir2 будут найдены файлы, совпадающие по содержимому с файлами в dir1, то они будут удалены из dir2.

Минусы: по идее, сначала надо проверить на дубликаты каждую директорию саму с собой (чтобы исключить наличие дублирующихся файлов в директории) и затем уже сравнивать друг с другом. Есть вероятность, что md5sum выдаст на разных файлах одинаковое хеш-значение (однако вероятность этого очень, очень мала, но для тех кто сомневается может заменить md5sum на sha384sum или sha512sum для большей уверенности).

Плюсы: все равно какие файлы сравнивать. Это не имеет значения.



oldbay 19.01.10 01:11 # +4
а если diff использовать ?
zivot_je_cudo 19.01.10 01:55 # +-3
Взбугагакнуло.
Minoru 19.01.10 05:04 # +0
А чего вы? Если вывод
diff file1 file2
пустой, значит, файлы одинаковые. При этом исключены коллизии (одинаковые хэши для разных файлов), т.к. никакие хэши вообще не считаются — идёт тупое сравнение.

Но подозреваю, что diff ощутимо медленнее md5sum работает.
digiwhite 19.01.10 06:33 # +0
Либо я чего-то не знаю, либо попробуйте применить diff для двоичных файлов.
commonD 19.01.10 13:02 # +1
diff отлично различает одинаковые двоичные файлы или разные.
digiwhite 19.01.10 13:19 # +0
Да-да. Проверил. Просто перед написанием скрипта тупанул и показалось что с бинарными файлами не работает.

Осталось сравнить скорости сравнения в том и в другом случае.
zivot_je_cudo 19.01.10 09:20 # +0
А что я? Согласен с комментом oldbay =)
digiwhite 19.01.10 06:33 # +0
Вы пробовали?
digiwhite 19.01.10 06:40 # +0
В общем-то диф конечно тоже можно использовать.
razum2um 19.01.10 05:04 # +0
digiwhite 19.01.10 06:31 # +0
Таки тащим Qt за собой?
razum2um 19.01.10 14:20 # +1
Да это ж не упрек.
И я тож люблю консоль, но это - так - другим в качестве альтернативы..
chemikadze 20.01.10 00:18 # +0
Там ссылка на скачивание старого кода, на гуглокоде по-свежее.
IamCrazy 19.01.10 08:22 # +0
А зачем оно все, если уже есть FSlint или fdupes.
xT 19.01.10 09:02 # +0
для практики
digiwhite 19.01.10 09:37 # +1
Вот пришел на работу, загрузил QNX4 и понял, что ничего из вами перечисленного там нет.
solomenikm 19.01.10 11:21 # +0
Если директории "близнецы", то вполне можно использовать для этой цели rsync.
digiwhite 19.01.10 11:27 # +0
Что подразумевается под "директориями-близнецами"?
solomenikm 19.01.10 11:57 # +1
Извините, то что я написал этот комментарий сведетельсвует что вчерашний день удался :)
cthscr 19.01.10 18:47 # +1
> *) echo "Bad";
> exit 0
Точно 0?
BTW, после прочтения http://tldp.org/LDP/abs/html/exitcodes.html я перестал использовать `exit 2`

>if [ $PARAM_NUMBER != 2 ] ; then
> echo "Wrong parameters number. Please use $ME";
> print_help
>fi
Мне одному кажется, что здесь что-то не так?

>if [ ! -d $DIR_1 ] ; then
Что произойдёт в случае:
$ mkdir /tmp/Test\ Dir
$ ./this_script_name -f /tmp/Test\ Dir/ -d whatever
?
digiwhite 19.01.10 20:32 # +0
BTW, после прочтения http://tldp.org/LDP/abs/html/exitcodes.html я перестал использовать `exit 2`

За ссылочку спасибо. Почитал, исправил для соответствия.


>if [ $PARAM_NUMBER != 2 ] ; then
> echo "Wrong parameters number. Please use $ME";
> print_help
>fi
Мне одному кажется, что здесь что-то не так?

Эм :) Это я тупо по привычке. В QNX для показа справки используется утилита use. Т.е что-то в стиле:
use cp

Поправил короче говоря :).

>if [ ! -d $DIR_1 ] ; then
Что произойдёт в случае:
$ mkdir /tmp/Test\ Dir
$ ./this_script_name -f /tmp/Test\ Dir/ -d whatever
?

Ничего. Скрипты выдаст ошибку, что параметр -d не соответствует ожидаемому параметру.
cthscr 20.01.10 14:02 # +1
>Ничего. Скрипты выдаст ошибку, что параметр -d не соответствует ожидаемому параметру.
Похоже, Вы не соизволили проверить. Намекну ещё раз: чем отличается поведение скриптов
DIR="somewhat with spaces"
if [ -d $DIR ];
и
DIR="somewhat with spaces"
if [ -d "$DIR" ];
?
digiwhite 20.01.10 23:17 # +0
Мда... не работает. Позже поищу как выйти из данной ситуации :) А можете и вы подсказать :).

Посты Комментарии
Последние посты
    Посты Комментарии
    Последние комментарии
      Посты Комментарии
      Изменения
        Посты Комментарии Изменения Черновики Избранное
        Черновики (все)
          Посты Комментарии Изменения Черновики Избранное
          Избранное (всё)
            Посты Комментарии Изменения Черновики Избранное
            Лучшие блоги (все 98)
            Топ пользователей Топ блогов
            Топ пользователей Топ блогов
            Элита (все 2016 из 153 городов)
            Топ пользователей Топ блогов
            В сети: Shtsh

            Новенькие: proton13, straton13, chipps, Dmitry.Minsky, zloyby
            welinux.ru

            Смотреть видео онлайн

            Онлайн видео бесплатно


            Смотреть русское с разговорами видео

            Online video HD

            Видео скачать на телефон

            Русские фильмы бесплатно

            Full HD video online

            Смотреть видео онлайн

            Смотреть HD видео бесплатно

            School смотреть онлайн