Сравните две папки и скопируйте / свяжите уникальные записи в новую папку
Как я могу скопировать все уникальные файлы из двух исходных папок в новую папку назначения?
Как заданная операция: Как я могу вычислить разницу между двумя папками?
4 ответа
Чтобы скопировать все файлы из 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
распечатать строки, найденные только в первом входном файле, и отбросить все остальное. (Примечание: это сломается, если какие-либо имена файлов содержат символы новой строки.)
Ничто из вышеперечисленного не сравнивает содержимое разных файлов просто потому, что я не уверен, что делать, если они разные. Изучение содержимого файла может использовать diff -r -q foo/ bar/
в качестве отправной точки, но что нам с этим делать?
Вы можете попробовать это:
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) интересует только прямое содержимое папки.
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) Вы также можете сравнить двоичные файлы, см. Stackru#4013223 и superuser#135911
Сначала я думал, что смогу решить эту проблему с умным использованием rsync
но на самом деле ничего не получалось.
Таким образом, моим окончательным решением был небольшой скрипт на Python (gist).