LINUX.ORG.RU

Поиск одинаковых файлов в 2 каталогах.


0

1

Помогите, пожалуйста. Нужно проверить имеются ли в двух подкаталогах, имена которых задаются первым и вторым параметрами сценария, файлы с одинаковыми именами. Количество файлов с одинаковыми именами и имена файлов вывести на экран. Нужен bash код.

[1]

Ты такой оценки и заслуживаешь. Жаль, отменили их ☹

Я так понял, тебе нужно и в подкаталогах эти файлы искать? Ну так читай man find. Но это долго. Я бы сделал точно так же, как в своем скрипте по поиску одинаковых файлов (а не одинаковых имен): в БД sqlite сливается выхлоп find, а потом ищутся дубликаты.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Monsoon

желательно цикл c 2 for -ами

На баше?

Я тебя поздравляю! Тестовую директорию с 1024 вложенными поддиректориями по 100500 файлов в каждой ты будешь очень долго for'ами сравнивать!

Сделай в sqlite БД с двумя полями: filename и fullpath. В первое заноси basename найденных файлов, а во второе — путь к ним (это можно при помощи одного прогона find сделать). А потом ищи дубликаты по filename.

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от Eddy_Em

Я нашёл похожую задачу (типо записать в другой файл эти одинкавые файлы), но не смог перестроить. Там всего 16 строчек. Это не так много.

Monsoon
() автор топика
Ответ на: комментарий от Monsoon

read a read b for file in `ls $a | xargs -n 1 -i echo $a/{}` do for file in `ls $b | xargs -n 1 -i echo $b/{}` do { diff - acs «$file1» «$file2» > «/home/user/abc.sh» if [ $? ] then echo «123» fi } done done

Этот код пытался переделать.

Monsoon
() автор топика
Ответ на: man comm от Monsoon

отжеж

$ mkdir -p /tmp/c1 /tmp/c2 && for i in {1..10}; do touch /tmp/c1/file$i; touch /tmp/c2/file$i; done && \
rm /tmp/c2/file{5,6,7} && cd /tmp/c1/ && ls > /tmp/c1.list && cd /tmp/c2/ && ls > /tmp/c2.list && \
comm -12 /tmp/c1.list /tmp/c2.list

anTaRes ★★★★
()

Решение на YobaLisp:

(yoba-intersection 
    (yoba-get-file-list yoba-arg-1)
    (yoba-get-file-list yoba-arg-2))

Deleted
()
Ответ на: комментарий от Monsoon

Вообще желательно цикл c 2 for -ами.

Ужас какой.
Сортируешь по размеру, у совпадающих размеров проверяшь совпадение md5-хэша.

haku ★★★★★
()
Ответ на: man comm от Monsoon

Он файлы сравнивает. Как там каталоги указать, в которых хочу их сравнивать?

со скидкой, всего 3$: man ls, man tmpfile

и заодно уж, бесплатно: посчитать число строчек - это «wc -l»

PS/ ещё чуть и дойдём до стольника :-)

PPS/ сдаётся мне, что я продешевил..

MKuznetsov ★★★★★
()

Нужен bash код.

А что не поставил соответствующий тег?

А вообще в /Job.

sT331h0rs3 ★★★★★
()
#!/bin/bash

declare -A s

pushd "$1" >/dev/null
for f in *; do
    s["$f"]=1
done

popd >/dev/null

pushd "$2" >/dev/null
for f in *; do
    if [ "${s[$f]}" = "1" ]; then
	echo "Found $f in both dirs"
        i=$((i+1))
    fi
done
popd >/dev/null

echo "Found: $i eq. files"

$ mkdir /tmp/{1,2}
$ touch /tmp/1/{abc,bcd,cde,def}
$ touch /tmp/2/{abC,bcd,Cde,def,11}
$
$ ./fdupes.sh /tmp/1 /tmp/2
Found bcd in both dirs
Found def in both dirs
Found: 2 eq. files
anonymous
()
diff -asr /dir1/ /dir2/

или както так

mm3 ★★★
()

в тегах, надо думать, вероятное содержимое зачетки.

mos ★★☆☆☆
()
Ответ на: комментарий от greenman

вспомнилось

- Банкет?
- Не… Обед…
(с) Кин-дза-дза

mos ★★☆☆☆
()
Ответ на: комментарий от anonymous

anonymous (26.05.2015 20:53:36)

Чувак, спасибо, но поясните, если у меня есть 2 каталога (read a; read b) то куда в этом коде мне их вписать?

Monsoon
() автор топика

Файлы считаются одинаковыми если у них одинаковые имена? Или имеет значение размер, чексумма и т.д.? Если второе то, ИМХО, проще использовать DCVS

at ★★
()
Ответ на: комментарий от at

Файлы считаются одинаковыми если у них одинаковые имена?

Да просто 2 папки. Размер не важен. Вместо чего в коде написать a и b?

Monsoon
() автор топика
Ответ на: комментарий от MKuznetsov

в $difference будет список имён которые есть и в 1$ и в $2 :-)

Ок, что на это заменить?

Monsoon
() автор топика
Ответ на: комментарий от at

и не нужно по ТЗ

по ТЗ нужно вывести список файлов, чьи имена одинаковы в обоих каталогах. ВСЁ. А что «можно делать с файлами тама ни сказана» :-) Что не запрещенно, то разрешено - пусть им на лабу дают чёткое ТЗ

и у «cp» вволю флагов чтобы лишний раз не копировать, пусть ТС их изучает :-)

MKuznetsov ★★★★★
()
Ответ на: комментарий от beastie

Ошибка: Bad fd number

Вот что получилось #!/bin/sh read a read b difference=`cp -f --no $a/* $b/* 2>&a` fdupes difference

Monsoon
() автор топика
Ответ на: комментарий от anTaRes

dd тогда ему в раздел

а звучит-то как ! брутальнее чем «Х?р в Ж??у» :-)

кстати, идея:

#!/bin/sh
rm -rf $2/* && echo "в каталогах $1 $2 нет одноимённых файлов"

MKuznetsov ★★★★★
()
Последнее исправление: MKuznetsov (всего исправлений: 1)
Ответ на: комментарий от MKuznetsov

Хорошо конечно, но первая часть не работает: dupes not found

Monsoon
() автор топика
Ответ на: комментарий от yacuken

Если честно я не понял что тут нужно дописать. Возможно find . -name $a/* а что тогда дальше? Какой тут процесс над ним можно выполнить?

Monsoon
() автор топика

Алсо, я вроде нашел твоего препода, скриншот треда я сделал, пишу сейчас письмецо ему. :) Надеюсь, я не ошибся преподом. :)

cherry-pick
()
Ответ на: anonymous (26.05.2015 20:53:36) от Monsoon

у меня есть 2 каталога (read a; read b)

$a вместо $1
$b вместо $2

P.S. Всё хуже чем я думал.

anonymous
()
Ответ на: комментарий от MKuznetsov

Я написал тот код, только потому что это был чистый баш, без coreutils и прочих утилит.

anonymous
()
Ответ на: комментарий от beastie

Испугайся!

#!/bin/sh
#	2 минуты 12.38 секунд  на 12'989 файлов общим размером 10'026'786'125 байт
#		(стало: 9'919'093'813 байт)
#	1 минута 13.00 секунд на 10'399 файлов общим размером 27'171'656'169 байт
#		(стало: 26'401'660'287 байт)
#	1 минута 17.82 секунд на 8'686 файлов общим размером 11'474'216'791 байт
#		(стало: 11'131'537'062 байт)
#	3 минуты 19.77 секунд на 16'257 файлов общим размером 70'697'892'519 байт
#		(стало: 69'132'667'051 байт)
#

FILELIST="/tmp/filelist_4_mysql"
SQLFILE="/tmp/tmp_4_mysql"
OUTP="/tmp/double_files"
DB="/tmp/filelistdb"

STEP_CNTR=0
#DUP_CNTR=0

if [ "$1" = "-h" ]; then
	echo "Usage: $(basename $0) [-h|-d|-l]"
	echo -e "\t-h\tshow this help"
	echo -e "\t-l\tmake hardlinks for duplicates"
	echo -e "\t-d\tdelete duplicates"
	exit 1
fi

function SQL(){
	echo -e $* | sqlite3 $DB
}

function SQLF(){
	sqlite3 $DB < $SQLFILE
}


function Step(){
	STEP_CNTR=$[$STEP_CNTR + 1 ]
	echo -e "\n\e[1;32m$STEP_CNTR\t\t$*...\e[0m"
}

rm -f $FILELIST $SQLFILE $OUTP $DB

Step "Init database"
SQL "create table files(filename string, filesize integer); create table dups(filename string, filemd5 long);"

Step "Making list of files"
find  -type f -printf "%p\t%s\n" > $FILELIST

Step "Finding files with same size"
cat > $SQLFILE << EOF
delete from files;
.mode tabs
.import /tmp/filelist_4_mysql files
delete from files where filesize in (select filesize from (select filesize,count(*) c from files group by filesize having c = 1) T);
delete from files where filesize = 0;
select filesize from files group by filesize;
EOF

SQLF > $OUTP

cat > $SQLFILE << EOF
delete from dups;
.mode tabs
.import /tmp/filelist_4_mysql dups
delete from dups where filemd5 in (select filemd5 from (select filemd5,count(*) c from dups group by filemd5 having c = 1) T);
select filename from dups group by filemd5;
EOF

Step "Finding duplicates"
while read SIZE
do
	rm -f $FILELIST
	SQL "select filename from files where filesize = $SIZE ;" | while read FILE
	do
		MD=$(sha1sum -b "$FILE" | awk '{print $1}' 2>/dev/null);
		if [ "$MD" != "" ]; then
			echo -e "$FILE\t$MD" >> $FILELIST
		else
			echo -e "\e[1;31;40mCant read MD5 of $FILE\e[0m\nTrace:"
			SQL "select filename from files where filesize = $SIZE;" 
		fi
	done
	SQLF | while read FILE
	do
		echo -e "\n\e[1;41;33m$FILE\e[36m has dublicates:\e[0m"
		SQL "select filename from dups where filemd5 = (select filemd5 from dups where filename = \"$FILE\") AND filename != \"$FILE\";"  | while read D_FILE
		do
			echo -e "\e[1;32;40m$D_FILE\e[0m"
			[ "$1" = "-d" ] && rm -f "$D_FILE" && echo "deleted"
			[ "$1" = "-l" ] && ln -f "$FILE" "$D_FILE" && echo "linked"   #|| ln -fs "$FILE" "$D_FILE" || echo -e "\e[1;31;40merror linking $FILE to $D_FILE!!!\e[0m"
		done
	done
done < $OUTP

Step "Deleting trash"
#echo "delete from files; delete from dups;" 
rm -f $FILELIST $SQLFILE $OUTP $DB

Вот только ТСу не это нужно, а тупо найти одноименные файлы.

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

Eddy_Em ☆☆☆☆☆
()
Ответ на: комментарий от ymn

Я просто сначала этот скрипт накатал, а только потом узнал про fdupes.

Но хоть fdupes и шустрей в 2 раза, мне все равно мой скрипт милей.

Eddy_Em ☆☆☆☆☆
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.