LINUX.ORG.RU

Пересечение и вычитание директорий


0

1

Директории с файлами — это деревья в терминологии теории графов. Если конечно, там нет жестких ссылок (символические ссылки можно считать особыми текстовыми файлами). А деревья можно, как известно, как минимум, объединять, прививать, умножать и вычитать.

Если с прививанием деревьев всё ясно — mv source_dir dest_dir/dir2/ например или то же самое с cp, то с остальными двумя операциями сложней.

Но кажется, объединять директории с помощью cp -r всё-таки можно:

$ mkdir -p sdir/{1,2,3}/{4,5,6}/{8,9}
xenius@xenote:~$ mkdir -p ddir/{2,3,4}/{5,6,7}
xenius@xenote:~$ cp -r -T sdir ddir
xenius@xenote:~$ tree ddir
ddir
├── 1
│   ├── 4
│   │   ├── 8
│   │   └── 9
│   ├── 5
│   │   ├── 8
│   │   └── 9
│   └── 6
│       ├── 8
│       └── 9
├── 2
│   ├── 4
│   │   ├── 8
│   │   └── 9
│   ├── 5
│   │   ├── 8
│   │   └── 9
│   ├── 6
│   │   ├── 8
│   │   └── 9
│   └── 7
├── 3
│   ├── 4
│   │   ├── 8
│   │   └── 9
│   ├── 5
│   │   ├── 8
│   │   └── 9
│   ├── 6
│   │   ├── 8
│   │   └── 9
│   └── 7
└── 4
    ├── 5
    ├── 6
    └── 7

36 directories, 0 files
$ rm -rf {s,d}dir

В общем, стандартный инструмент для сложения директорий есть.

А есть ли стандартные инструменты для вычитания директорий?

a) Скопировать в директорию C все те и только те файлы, которые есть в директории A, но которых нет в директории B b) Удалить из директории A все и только те файлы, копии которых есть в директории B Даже два варианта вычитания. И к каждому из них можно добавить критерии проверки: считать идентичными файлы с одинаковыми путями или файлы, которые с одинаковыми путями и одинаковым содержимым. И два варианта вывода результата: в уменьшаемой директории или отдельно.

Кроме того, можно ещё построить пересечение директорий — все файлы, которые есть в обоих директориях и находятся по одному пути. Другой вариант — учитывать и содержимое.

Однако, пересечение директорий можно получить вычетанием: A * B = A - (A - B).

Так вот, существуют ли утилиты, позволяющие выполнять вычитание деревьев директорий или только самому заморачиваться с find, sort comm и md5sum? А то пока приходит в голову только такой пример — с помощью find и exec вывести список файлов совместно с их md5, а потом с помощью comm выбрать пересечение (comm -3) или одно из направлений вычитания (comm -1 или comm -2), но в данном случае возникнут проблемы с нестандартными символами в именах файлов.

★★★★★

на Ruby можно вычитать массивы, поэтому напиши короткий скрипт, который получать две директории, а на выходе выдавать их разность

xapienz
()
Ответ на: комментарий от Reset

> существуют. такая утилита называется perl
Ты бы ещё сказал «существует, такая утилита назвается hex-редактор».

Мне готовое надо, или придётся писать скрипт на баше

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

То есть вычитание директорий уже реализовано?

Кстати говоря, я видел такой скриптик, только он мне похерил немало нужных файлов, ибо симлинки не отличал от настоящих директорий.

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

Нет, надо писать. Составляем два списка, сортируем, потом делаем что нужно.

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

Что-то мне эта команда не нравится. Желательно что бы она гарантированно правильно обрабатывала файлы с любыми именами

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

> похоже на олимпиадную задачу. у этого есть какая-то практическая цель?
Есть. Берём старый и новый бекап, чистим старый бекап и вместо 2x места бекапы занимают только 1.2x скажем. Инкрементальный хуже тем, что для восстановления требуется слишком много частей.

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

я просто последовательность бэкдифов храню... то есть та самая разница между новым и старым состоянием (старое - новое). не прямые диффы (новое - старое) - потому что так хранится именно актуальное состояние и можно удалять любое количество бэкдиффов последовательностью начиная с самых старых, причем не нарушается целостность архива.

кстати тоже пришлось свою реализацию писать, т.к. rsync не умеет работать со снимком состояния вместо самого снапшота. набыдлокодил на питоне :)

основной алгоритм - простейший рекурсивный сравнитель отсортированных списков содержимого директорий. то есть скажем есть 2 списка

a b c d
b c e f
и оно обрабатывает пары
None a
b b
c c
d None
None e
None f
если оба элемента - директории, то рекурсивно спускаемся в оба. если только 1 элемент - директория, то рекурсивно спускаемся в него, а другой элемент будет для всего содержимого None.

меняя обработчик пар, можно все описанные операции реализовать.

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

А если на обе директории сделать find dir -exec md5sum \; | sort, воспользоваться comm и просто удалить общие директории по полученному списку?

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