Как объединить один каталог в другой с помощью Bash?


Я ищу скрипт, чтобы объединить файлы из одного каталога в другой.

пример:

html/
  a/
    b.html
  index.html

html_new/
  a/
    b2.html
    b.html

использование:

./mergedirs.sh html html_new

результат:

html/
  a/
    b.html
    b2.html
  index.html

html/a/b.html был заменен html_new/a/b.html
html/a/b2.html был скопирован из html_new/a/b2.html
html/index.html был сохранен нетронутым

7 60

7 ответов:

Вы наверное просто хотите cp -R /* / - Это рекурсивная копия.

(Если там могут быть скрытые файлы (те, чьи имена начинаются с точки), вы должны префикс команды с shopt -s dotglob; чтобы убедиться, что они совпадают.)

cp -RT source/ destination/

все файлы и каталоги в source в конце destination. Например, source/file1 будет скопировано в destination/file1.

The -T останавливается флаг source/file1 от копирования к destination/source/file1 вместо.

взгляните на rsync

rsync --recursive html/ html_new/

Rsync получил много флагов, чтобы установить так что смотрите на rsync manpage для деталей

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

rsync -av /path/to/source_folder/ /path/to/destination_folder/

обратите внимание, что конечная косая черта в исходной папке необходима для копирования только содержимого папки source_folder в пункт назначения. Если вы оставите его, он будет копировать source_folder и это содержание, которое, вероятно, не то, что вы ищете, так как вы хотите объединить их.

cd html
cp -r . /path/to/html_new

не cp -r работы?

cp -r html_new/* html

или (так как первая версия не будет копировать ".что-то" - файлы)

cd html_new; cp -r . ../html

обратите внимание:-rчитает из трубы если какие-либо файлы в скопированном каталоге являются трубами. Чтобы избежать этого, используйте .

несмотря на то, что этот вопрос и его принятый ответ являются древними, я добавляю свой ответ, потому что существующие в настоящее время используют cp либо не обрабатывайте некоторые крайние случаи, либо требуйте интерактивной работы. Часто edge-cases / scriptability / portability / multiple-sources не имеют значения, хотя в этом случае выигрывает простота, и лучше использовать cp непосредственно с меньшим количеством флагов (как и в других ответах), чтобы уменьшить когнитивную нагрузку - но для тех другое раз (или для робастно многоразовая функция) этот вызов/функция полезна, и, кстати, не является специфичным для bash (я понимаю, что этот вопрос был о bash, так что это просто бонус в этом случае). Некоторые флаги могут быть сокращены (например,-a), но я включил все явно в форме (за исключением -R, см. ниже) ради объяснения. Очевидно, просто удалите любые флаги, если есть какая-то функция, которую вы специально не хотите (или вы находитесь на не-posix ОС, или ваша версия cp не обрабатывает этот флаг - я проверил это на GNU coreutils 8.25 х cp):

mergedirs() {
    _retval=0
    _dest=""
    shift
    yes | \
        for _src do
            cp -R --no-dereference --preserve=all --force --one-file-system \
                  --no-target-directory "${_src}/" "$_dest" || { _retval=1; break; }
        done 2>/dev/null
    return $_retval
}

mergedirs destination source-1 [source-2 source-3 ...]

объяснение:

  • -R: имеет слегка различную семантику от -r/--recursive в некоторых системах (особенно в отношении специальных файлов в исходных dirs), как описано в ответ
  • --no-dereference: никогда не переходите по символическим ссылкам в SOURCE
  • --preserve=all: сохранение указанных атрибутов (по умолчанию: режим,право собственности,метки), если это возможно, дополнительные атрибуты: контекст, ссылки, xattr, все
  • --force: если существующий файл назначения не может быть открыт, удалите его и повторите попытку
  • --one-file-system: оставайтесь в этой файловой системе
  • --no-target-directory: обработайте DEST как нормальный файл (объясненный внутри в ответ, а именно: If you do a recursive copy and the source is a directory, then cp -T copies the content of the source into the destination, rather than copying the source itself.)
  • [piped input from yes]: даже с --force, в этом конкретном рекурсивном режиме cp еще просит перед тем, как забивать каждый файл, мы достигаем неинтерактивности, выводя вывод из yes это
  • [трубам вывод /dev/null]: это для того, чтобы заставить замолчать беспорядочную строку вопросов по строкам cp: overwrite 'xx'?
  • [return-val & early exit]: это гарантирует, что цикл завершается, как только есть неудачная копия, и возвращает 1 если произошла ошибка

кстати:

  • фанки новый флаг, который я также использую на моей системе это --reflink=auto для выполнения так называемых" легких копий " (копирование на запись, с той же скоростью, что и жесткая компоновка, и тот же размер выгоды до и обратно пропорционально тому, насколько файлы расходятся в будущем). Этот флаг принят в недавнем GNU cp, и делает больше, чем no-op с совместимыми файловыми системами на последних ядрах Linux. YMWV много других систем.