
У меня есть несколько дубликатов файлов в каталогах A
, B
как мне удалить дубликаты, B
используя имена файлов A
в bash?
Как это сделать в других оболочках — приятный бонус.
решение1
В одну сторону:
#!/bin/bash
cd ~/B
for file in ~/A/*
do
file1=$(basename "$file")
[ -f "$file1" ] && { echo "deleting $file1 "; rm -- "$file1"; }
done
решение2
В одну строку
grep -f <(ls "A") <(ls "B") | xargs -I'{}' rm "B/{}"
но его работа зависит только от имени файла и может повлиять на пустые подкаталоги. Чтобы избежать этого, используйте find -type f -maxdepth 1
вместо ls
.
Для более безопасной проверки используйте рецепт @KasyA.
решение3
find /path/to/dirA -type f -exec cmp -s '{}' '/path/to/dirB/{}' \; -exec echo rm -v '/path/to/dirB/{}' \;
В тесте:
$ ls -1 /path/to/dirA
dupfile
file1inA
$ ls -1 /path/to/dirB
dupfile
file1inB
find /path/to/dirA -type f -exec cmp -s '{}' '/path/to/dirB/{}' \; -exec echo rm -v '/path/to/dirB/{}' \;
rm -v /path/to/dirB/./dupfile
примечание: удалите echo
, который используется для холостого хода.
решение4
cd B
ls ../
A
B
comm <(ls ../A) <(ls ./) -1 -2 -z | xargs -0 rm
comm
показывает три столбца,
- уникальный для файла1(A)
- уникальный для файла2(B)
- существуют на обоих
Поэтому мы удаляем столбец 1, 2 на -1 -2
. -z
будет использовать NULL в качестве разделителя. По умолчанию `\n' новая строка.
При работе с каналом и списком произвольных строк, таких как имя файла, передача с разделителем NULL безопасна.