Як об’єднати один каталог в інший за допомогою Bash?


78

Я шукаю сценарій оболонки, який об’єднує файли з одного каталогу в інший.

Зразок:

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було збережено незайманим


1
Пробували cp -r html_new/* html? Після цього можна видалити html_newкаталог.
ismail

Відповіді:


86

Ви, мабуть, просто хочете cp -R $1/* $2/- це рекурсивна копія.

(Якщо можуть бути приховані файли (ті, чиї імена починаються крапкою), вам слід shopt -s dotglob;додати до цієї команди префікс, щоб переконатися, що вони збігаються.)


96
cp -RT source/ destination/

Всі файли та каталоги в sourceопиняться в destination. Наприклад, source/file1буде скопійовано в destination/file1.

Натомість -Tпрапор не source/file1копіюється destination/source/file1. (На жаль, cpна macOS не підтримує -Tпрапор.)


працює добре, копіює та об’єднує / folder / data у folder2 / data
nwgat

2
Я вважаю це рішення тим, що воно працює "як є" з .dotfiles.
fnkr

6
У Mac OS X / darwin ви захочете використовувати cp -r source/ destination- досить складно використовувати / точно так, як вказано.
Рон Вертлен,

Пишаюся тим, що голосую за цю відповідь, і тому тепер вона дорівнює поточній прийнятій 😄.
Hadrien TOMA

Зверніть увагу: буде перезаписано всі файли в пункті призначення, які мають те саме ім’я, що і джерело
brianegge

17

Погляньте att rsync

rsync --recursive html/ html_new/

Rsync має багато прапорів для встановлення, тому дивіться детальнішу інформацію на rsync manpage


6

Просто використовуйте rsync - це чудовий інструмент для локального копіювання та об'єднання файлів на додаток до віддаленого копіювання.

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

Зауважте, що кінцева скісна риска у вихідній папці необхідна для копіювання лише вмісту source_folder до місця призначення. Якщо його залишити, він скопіює папку source_folder та її вміст, що, мабуть, не те, що ви шукаєте, оскільки ви хочете об’єднати папки.


є маленька друкарська помилка, зайвий дефіс, так і повинно бутиrsync -av /path/to/source_folder/ /path/to/destination_folder/
vim

4

Незважаючи на те, що це запитання та прийнята відповідь давні, я додаю свою відповідь, оскільки існуючі в даний час питання, які використовують cpабо не обробляють деякі крайні випадки, або вимагають інтерактивної роботи. Часто крайні випадки / сценарій / переносимість / кілька джерел не мають значення, проте в такому випадку простота перемагає, і краще використовувати cpбезпосередньо меншу кількість прапорців (як в інших відповідях), щоб зменшити когнітивне навантаження - але для тих інших часів (або для надійно використовуваної функції) це виклик / функція корисна і, до речі, не є специфічною для bash (я розумію, що це питання стосувалося bash, тому це просто бонус у цьому випадку). Деякі прапори можуть бути скороченими (наприклад, з -a), але я включив усі явно у довгій формі (за винятком-R, див. нижче) для пояснення. Очевидно, просто видаліть будь-які прапори, якщо є якась функція, яка вам конкретно не потрібна (або ви перебуваєте в не-posix ОС, або ваша версія cpне обробляє цей прапор - я протестував це на GNU coreutils 8.25's 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: ніколи не переходьте за символічними посиланнями у ДЖЕРЕЛІ
  • --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, у цьому конкретному рекурсивному режимі cpвсе ще запитується перед обробкою кожного файлу, тому ми досягаємо неінтерактивності, виводячи трубопровід yesдо нього
  • [виведення в трубопроводі /dev/null]: це для того, щоб замовкнути безладну низку запитань у напрямкуcp: overwrite 'xx'?
  • [return-val & ранній вихід]: це забезпечує вихід циклу, як тільки 1є помилкова копія, і повернення, якщо сталася помилка

ДО:

  • Новий прикольний прапор, який я також використовую з цим у своїй системі, - це --reflink=autoробити так звані "легкі копії" (copy-on-write, з тими самими перевагами швидкості, що і жорсткі посилання, і тими ж перевагами розміру до і у зворотній пропорції наскільки файли розходяться в майбутньому). Цей прапор прийнятий в останній GNU cpі робить більше, ніж не застосовувати сумісні файлові системи на останніх ядрах Linux. YMWV-багато в інших системах.


2

Не cp -rвийде?

cp -r html_new/* html

або (оскільки перша версія не копіює файли ".something")

cd html_new; cp -r . ../html

Зверніть увагу, що -r зчитування з каналів, якщо будь-який із файлів у скопійованому каталозі є каналами. Щоб цього уникнути, використовуйте -Rзамість цього.


При "об'єднанні" декількох каталогів тощо розгляньте також -n(без клоббера) або -f(примусово) можливість зберегти існуючі файли або перезаписати їх.
Томаш Гандор,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.