Я хотел бы скопировать набор файлов из каталога A в каталог B с оговоркой, что если файл в каталоге A идентичен файлу в каталоге B, этот файл не должен копироваться (и, следовательно, время его модификации не должно быть обновлено). Есть ли способ сделать это с помощью существующих инструментов, без написания собственного сценария?
Чтобы немного рассказать о моем сценарии использования: я автоматически .c
генерирую группу файлов во временном каталоге (методом, который должен генерировать все из них безоговорочно), и когда я их заново генерирую, я хотел бы только скопировать те, которые превратились в фактический исходный каталог, оставляя неизменными (с их старым временем создания), чтобы make
знать, что не нужно их перекомпилировать. (Однако не все сгенерированные файлы являются .c
файлами, поэтому мне нужно делать двоичные сравнения, а не текстовые сравнения.)
(Примечание: это выросло из вопроса, который я задал на https://stackoverflow.com/questions/8981552/speeding-up-file-comparions-with-cmp-on-cygwin/8981762#8981762 , где я пытался чтобы ускорить файл сценария, который я использовал для выполнения этой операции, но мне пришло в голову, что я действительно должен спросить, есть ли лучший способ сделать это, чем написание собственного сценария - тем более, что любой простой способ сделать это в оболочке скрипт будет вызывать что-то вроде cmp
каждой пары файлов, и запуск всех этих процессов занимает слишком много времени.)
источник
diff -qr dirA dirB
чтобы увидеть, какие файлы являются уникальнымиdirA
иdirB
, соответственно.rsync -avnc
или длинный путьrsync --archive --verbose --dry-run --checksum
.Ответы:
rsync, вероятно, лучший инструмент для этого. У этой команды много опций, поэтому прочитайте man-страницу . Я думаю, что вы хотите параметр --checksum или --ignore-times
источник
-t
указана опция), либо со временем синхронизации (если-t
не указано).rsync
не делает. Если я делаю это:,mkdir src dest; echo a>src/a; rsync -c src/* dest; sleep 5; touch src/a; rsync -c src/* dest
тоstat dest/a
показывает, что его mtime и ctime на 5 секунд старше, чем уsrc/a
.--checksum
опция, и хотя linux.die.net/man/1/rsync не содержит абсолютно ничего, что могло бы повлиять на то, обновляется ли дата модификации, тем не менее, это приводит к тому, что конечная дата модификации будет оставлена нетронутым. (С другой стороны,--ignore-times
опция не имеет такого эффекта; с ней дата модификации все еще обновляется.) Однако, учитывая, что это кажется совершенно недокументированным, могу ли я на это положиться?rsync
рабочий процесс: 1) проверить, нужно ли обновлять файл; 2) если так, обновите файл.--checksum
Вариант сказать , что это не должно обновляться, поэтомуrsync
не следует перейти к шагу 2).--ignore-times
без--checksum
копирует каждый файл, а также обновляет метку времени, даже если файлы идентичны.Вы можете использовать
-u
переключатель, чтобыcp
понравиться так:Со страницы руководства:
источник
-u
делает флаг и как он работает, и как это могло бы помочь ОП. Однако в данном конкретном случае это не помогло бы OP, поскольку оно скопировало бы идентичные файлы, если бы они были более новыми, и поэтому изменило бы свои метки времени, чего именно и хочет избежать OP.В то время как использование
rsync --checksum
является хорошим общим способом «копировать, если изменено», в вашем конкретном случае есть еще лучшее решение!Если вы хотите избежать ненужной перекомпиляции файлов, вы должны использовать ccache, который был создан именно для этой цели! Фактически, это не только позволит избежать ненужных перекомпиляций ваших автоматически сгенерированных файлов, но также ускорит процесс, когда вы это сделаете,
make clean
и перекомпилируете с нуля.Затем я уверен, что вы спросите: "Это безопасно?" Ну да, как указывает сайт:
И его легко использовать , просто добавив его в качестве префикса в
CC=
строке вашего make-файла (или вы можете использовать символические ссылки, но способ make-файла, вероятно, лучше).источник
ccache file.c -o file.o
или эквивалентный, несколько сотен раз, потому что есть несколько сотенfile.c
файлов. Когда я делал это сcmp
, а неccache
, это заняло несколько минут - иcmp
так же легко, какccache
. Проблема в том, что на Cygwin запуск процесса занимает немалое время, даже для совершенно тривиального процесса.for f in src/*; do /bin/true.exe; done
занимает 30 секунд, так что да. В любом случае, я предпочитаю свой редактор на базе Windows, и помимо такого рода проблем с синхронизацией Cygwin довольно хорошо работает с моим рабочим процессом как легкое место для локального тестирования, если я не загружаю их на серверы сборки. Полезно, чтобы моя оболочка и мой редактор были в одной ОС. :)Это должно делать то, что вам нужно
Где:
источник
-J
непереносимо ( специфично для bsd; с GNU xargs это так-I
) и не работает правильно, если один и тот же набор файлов уже не существует в обоих местах (если яtouch x/boo
тогда grep дает мнеOnly in ./x: boo
что вызывает ошибки в конвейере). Используйте инструмент, созданный для работы, какrsync --checksum
.Мне нравится использовать унисон в пользу,
rsync
потому что он поддерживает несколько мастеров, уже настроив мои ключи ssh и vpn отдельно.Так что в моем crontab только одного хоста я позволяю им синхронизироваться каждые 15 минут:
Тогда я могу развиваться с любой стороны, и изменения будут распространяться. Фактически для важных проектов у меня есть до 4 серверов, отражающих одно и то же дерево (3 запускают унисон из cron, указывая на тот, который не работает). На самом деле, Linux и Cygwin хосты смешаны - за исключением того, что не ожидают смысла в мягких ссылках в win32 вне среды cygwin.
Если вы идете по этому пути, сделайте начальное зеркало на пустой стороне без
-batch
, т.е.Конечно, есть конфигурация для игнорирования файлов резервных копий, архивов и т.д .:
источник
unison
опцию, которая означает «не обновлять даты последнего изменения файла». Есть один? В противном случае, это отличный ответ на совершенно другую проблему.-times
делает это для меня. У меня в Unison тоже есть пробный режим, мне кажется.times=false
(или отключение-times
) сделает это. Я не знаю, как я пропустил это в документации раньше. Благодарность!Хотя
rsync --checksum
это правильный ответ, обратите внимание, что эта опция несовместима--times
и--archive
включает в себя--times
, так что если вы хотитеrsync -a --checksum
, вам действительно нужноrsync -a --no-times --checksum
.источник