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

Смотреть hd видео

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

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

18.01.2010 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
#!/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 и подсчет для каждого файла хеш-значения с помощью md5sum (можно так же использовать sha1sum, sha224sum, sha256sum и т.п.), и запись пары {хеш-значение, имя файла} в другой список.

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

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


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

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

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


Тэги: bash shell директория скрипт сравнение файл
+ 4 -
Похожие Поделиться

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

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

Осталось сравнить скорости сравнения в том и в другом случае.
zivot_je_cudo 19.01.2010 09:20 #
+ 0 -
А что я? Согласен с комментом oldbay =)
digiwhite 19.01.2010 06:33 #
+ 0 -
Вы пробовали?
digiwhite 19.01.2010 06:40 #
+ 0 -
В общем-то диф конечно тоже можно использовать.
razum2um 19.01.2010 05:04 #
+ 0 -
digiwhite 19.01.2010 06:31 #
+ 0 -
Таки тащим Qt за собой?
razum2um 19.01.2010 14:20 #
+ 1 -
Да это ж не упрек.
И я тож люблю консоль, но это - так - другим в качестве альтернативы..
chemikadze 20.01.2010 00:18 #
+ 0 -
Там ссылка на скачивание старого кода, на гуглокоде по-свежее.
IamCrazy 19.01.2010 08:22 #
+ 0 -
А зачем оно все, если уже есть FSlint или fdupes.
xT 19.01.2010 09:02 #
+ 0 -
для практики
digiwhite 19.01.2010 09:37 #
+ 1 -
Вот пришел на работу, загрузил QNX4 и понял, что ничего из вами перечисленного там нет.
solomenikm 19.01.2010 11:21 #
+ 0 -
Если директории "близнецы", то вполне можно использовать для этой цели rsync.
digiwhite 19.01.2010 11:27 #
+ 0 -
Что подразумевается под "директориями-близнецами"?
solomenikm 19.01.2010 11:57 #
+ 1 -
Извините, то что я написал этот комментарий сведетельсвует что вчерашний день удался :)
cthscr 19.01.2010 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.2010 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.2010 14:02 #
+ 1 -
>Ничего. Скрипты выдаст ошибку, что параметр -d не соответствует ожидаемому параметру.
Похоже, Вы не соизволили проверить. Намекну ещё раз: чем отличается поведение скриптов
DIR="somewhat with spaces"
if < -d $DIR >;
и
DIR="somewhat with spaces"
if < -d "$DIR" >;
?
digiwhite 20.01.2010 23:17 #
+ 0 -
Мда... не работает. Позже поищу как выйти из данной ситуации :) А можете и вы подсказать :).

В хорошем качестве hd видео

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


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

Online video HD

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

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

Full HD video online

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

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

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