Несмотря на то, что этот вопрос и его принятый ответ являются древними, я добавляю свой ответ, потому что существующие в настоящее время использующие cp
либо не обрабатывают некоторые крайние случаи, либо требуют интерактивной работы.Часто крайние случаи / scriptable / portability / множественные источники не имеют значения, хотя, в этом случае простота выигрывает, и лучше использовать cp
напрямую с меньшим количеством флагов (как в других ответах), чтобы уменьшить когнитивную нагрузку - но дляэти другие раза (или для многократно используемой функции) этот вызов / функция полезен и, кстати, не относится к bash (хотя я понимаю, что этот вопрос касался bash, так что в данном случае это всего лишь бонус).Некоторые флаги могут быть сокращены (например, с -a
), но я включил все явно в длинную форму (за исключением -R
, см. Ниже) для пояснения.Очевидно, просто удалите все флаги, если есть какая-то особенность, которую вы не хотите (или вы используете не-posix ОС, или ваша версия cp
не обрабатывает этот флаг - я проверял этов GNU coreutils 8.25 cp
):
mergedirs() {
_retval=0
_dest="$1"
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
в некоторых системах(особенно в отношении специальных файлов в исходных каталогах), как объяснено в этот ответ --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.
) - [канальный ввод от
yes
]: даже с --force
, в этом конкретном рекурсивном модеe cp
все еще спрашивает перед тем, как загромождать каждый файл, поэтому мы достигаем неинтерактивности, передавая вывод из yes
в него - [конвейерный вывод в
/dev/null
]: это заставляет замолчать грязную строку вопросовпо линиям cp: overwrite 'xx'?
- [return-val & early exit]: это гарантирует, что цикл завершается сразу же после сбоя копии, и возвращает
1
, если произошла ошибка
КСТАТИ:
- Причудливый новый флаг, который я также использую с этим в моей системе, -
--reflink=auto
для выполнения так называемых «легких копий» (копирование при записи, ста же скорость дает преимущества, что и жесткие ссылки, и тот же размер выигрывает до и обратно пропорционально тому, насколько сильно файлы расходятся в будущем).Этот флаг принят в недавнем GNU cp
и делает больше, чем просто запрет совместимых файловых систем в последних ядрах Linux.YMWV-много в других системах.