Сравните две папки и скопируйте / свяжите уникальные записи в новую папку - PullRequest
2 голосов
/ 21 марта 2012

Как я могу скопировать все уникальные файлы из двух исходных папок в новую папку назначения?

Как операция набора: Как я могу вычислить разницу между двумя папками?

Ответы [ 4 ]

3 голосов
/ 22 марта 2012

Вы можете попробовать это:

cd <First Dir>
find . > /tmp/first.dat
cd <Second Dir>
find . > /tmp/second.dat
comm -23 /tmp/first.dat /tmp/second.dat | while read line; do cp <First Dir>/$line <New Dir> ; done
comm -13 /tmp/first.dat /tmp/second.dat | while read line; do cp <SecondDir>/$line <New Dir> ; done
1 голос
/ 21 марта 2012

Чтобы скопировать все файлы из foo/ и bar/ в baz/, самый простой способ - просто скопировать оба файла и позволить одному перезаписать другой:

cp --recursive foo/ baz/
cp --recursive bar/ baz/

Если вы хотите быть немного чище, а не копировать из bar/ все, что существует в foo/, вы можете написать:

cp --recursive foo/ baz/
( cd bar/
  find -exec bash -c ' if ! [[ -e ../foo/"{}" ]] ; then
                         cp "{}" ../baz/"{}"
                       fi
                     ' \;
)

Вы можете использовать тот же подход для генерации списка файлов в bar/, которые не существуют в foo/:

( cd bar/
  find -exec bash -c ' if ! [[ -e ../foo/"{}" ]] ; then
                         echo bar/"{}"
                       fi
                     ' \;
)

(или вы можете изменить echo bar/"{}" на printf %s\0 bar/"{}", чтобы использовать в качестве разделителя байт с нулевым значением, а не символ новой строки).

В качестве альтернативы вы можете написать:

diff --old-line-format=%L --new-line-format= --unchanged-line-format= \
     <( cd foo/ ; find | sort ) <( cd bar/ ; find | sort )

, который передает выходные данные cd foo/ ; find | sort и cd bar/ ; find | sort в diff в качестве входных файлов и указывает diff распечатать строки, которые найдены only в первом входном файле и откажитесь от всего остального. (Примечание: это прервется, если какие-либо имена файлов будут содержать новые строки.)

Ничто из вышеперечисленного не сравнивает содержимое разных файлов просто потому, что я не уверен, что делать, если они разные. Изучение содержимого файла может использовать diff -r -q foo/ bar/ в качестве отправной точки, но что нам с этим делать?

1 голос
/ 21 марта 2012

Я уверен, что есть другие способы (без дополнительных файловых операций, предложенных здесь), но вот относительно простой способ сделать это.

Допущения:
A1) Интересует толькопрямое содержимое папки.
A2) Предполагается, что файлы с одинаковым именем имеют идентичное содержимое.

1) создайте / используйте пустой временный каталог (tmp)
2) скопируйте содержимоеsourceDir1 в tmp
3) удалить содержимое sourceDir2 из tmp
- Теперь у вас есть уникальные файлы sourceDir1 в tmp
4) переместить содержимое tmp в нужное место
5) повторитьшаги 2) -4) с заменой ролей sourceDir1 и sourceDir2

Примечания:
N1) Вы можете использовать ls для вывода списка файлов (или каталогов) и перенаправления его в файл(скажем, s1.tmp).Затем вы можете сравнить список файлов (каталогов) другой папки, используя grep, чтобы увидеть, указан ли текущий файл (каталог) в s1.tmp.Вы можете использовать эту технику, чтобы вычислить, какие каталоги вводить для рекурсивной обработки (таким образом ослабляя A1)).
N2) Если речь идет о текстовых файлах, вы можете использовать diff, чтобы увидеть, идентичны ли они.Если да, действуйте как прежде, иначе обработайте случай идентичного имени файла, различного содержания соответственно (например, скопируйте оба файла в каталог назначения, используя уникальные расширения, чтобы указать их источник - логика здесь зависит от вашей цели).
N3Вы также можете сравнить двоичные файлы, см. stackoverflow # 4013223 и superuser # 135911

0 голосов
/ 22 марта 2012

Сначала я думал, что смогу решить эту проблему с умным использованием rsync, но на самом деле ничего не получалось.

Итак, моим окончательным решением был маленький Python-скрипт (gist) .

...