Як скопіювати і об'єднати два каталоги?


112

У мене в Linux є два каталоги images та images2 з цією структурою:

/images/ad  
/images/fe  
/images/foo  

... та інші 4000 папок

а інше схоже:

/images2/ad  
/images2/fe  
/images2/foo

... та інші 4000 папок

Кожна з цих папок містить зображення, а назви каталогів під зображеннями та images2 точно однакові, проте їх зміст різний. Тоді я хочу знати, як я можу скопіювати та об’єднати зображення / images2 / ad у зображення / ad, зображення / images2 / foo у зображення / foo тощо тощо з усіма 4000 папками ..


1
чи кінцеві файли в обох каталогах однакові?
Simply_Me

Ні ... наприклад, зображення / оголошення - 1.jpg, 2.jpg і 3.jpg. Але в images2 / ad є 4.jpg та 5.jpg
ssierral

4
@AmirAliAkbari, я не думаю, що це дублікат - інше питання, в основному, "Чи зростає mv?" (відповідь: ні). Це питання стосується того, як об’єднати 2 ієрархії каталогів.
maxschlepzig

Відповіді:


173

Це робота для rsync . Немає користі робити це вручну з циклом оболонки, якщо ви не хочете перемістити файл, а не скопіювати їх.

rsync -a /path/to/source/ /path/to/destination

У вашому випадку:

rsync -a /images2/ /images/

(Зверніть увагу на те images2, що слід накреслити , інакше воно буде скопійовано /images/images2.)

Якщо зображення з тим же ім'ям існує в обох каталогах, вищенаведена команда буде перезаписувати /images/SOMEPATH/SOMEFILEз /images2/SOMEPATH/SOMEFILE. Якщо ви хочете замінити лише старіші файли, додайте параметр -u. Якщо ви хочете завжди зберігати версію /images, додайте опцію --ignore-existing.

Якщо ви хочете перемістити файли з /images2, за допомогою rsync, ви можете передати цю опцію --remove-source-files. Потім rsync копіює всі файли по черзі та видаляє кожен файл, коли це зроблено. Це набагато повільніше, ніж переміщення, якщо каталоги джерела та призначення знаходяться в одній файловій системі.


14
..add -P, якщо ви хочете побачити прогрес ..
Meetai.com

1
Я хотів би додати , що немає ніякої користі , використовуючи хитру петлю оболонки тут , навіть якщо ви дійсно хочете , щоб перемістити їх замість того , щоб копіювати їх-в цьому випадку просто використовувати rsync, а потім rm -r /images.
Wildcard

1
Я також хотів би зазначити, що важливо включити проміжні риски для кожного каталогу . Наприклад, якщо ви просто запустили rsync -a images images2, він просто скопіює images2 у зображення, а не об'єднати їх.
Кайл Чалліс

1
@ s3cur3 О. Від 2 до (неявно) 1. Це неінтуїтивно. Дякую, я виправив свою відповідь.
Жиль

1
@MaxCoplan No. Ні. Rsync не є інтерактивним інструментом.
Жиль

43

Найкращий вибір, як уже було опубліковано, - звичайно, rsync. Тим не менш, також унісон був би чудовим програмним забезпеченням для цієї роботи. Обидва можна використовувати в декількох операційних системах.

Rsync

rsync синхронізується в одному напрямку від джерела до місця призначення. Тому наступне твердження

rsync -avh --progress Source Destination

синхронізує все від джерела до пункту призначення . Об'єднана папка знаходиться в пункті призначення .

означає "архів" і копіює все рекурсивно від джерела до місця призначення, зберігаючи майже все.

-v дає більше результатів ("багатослівний").

-h для людини читабельним.

- прогрес, щоб показати, скільки роботи зроблено.

Якщо ви хочете тільки оновити в цільову папку з новими файлами з вихідної папки:

rsync -avhu --progress source destination

Унісон

Унісон синхронізується в обох напрямках. Тому наступне твердження

unison Source Destination

синхронізує обидва каталоги в обох напрямках і, нарешті, джерело дорівнює призначенню. Це як робити rsync двічі від джерела до dest та навпаки.

Для більш просунутих звичаїв перегляньте сторінки man або наступні веб-сайти:

  1. https://www.cis.upenn.edu/~bcpierce/unison/
  2. https://rsync.samba.org/

2
Хочу зазначити, що правильний шлях до папки повинен бути з кінцевою косою рисою в кінці rsync -avh --progress source/ destination/, інакше папка-джерело буде створена в папці призначення, принаймні в моєму випадку, що так було.
електроїд

Це чудово працює для мене (з прорізною косою рисою в папках). Дякую!
Леопольдо Санчик

5
for dir in images2/*; do mv "$dir"/* "images/$(basename "$dir")"; done

Проведіть цикл на весь вміст images2використання розгорнутого глобуса (щоб уникнути проблем з розбором ls), а потім mvна вміст цих елементів до відповідного запису images. Використовує basenameдля того, щоб позбавити провідних images2від земної кулі.


будь ласка, додайте більше подробиць про те, що робить ваша команда, щоб вона була корисною і майбутнім читачам :)
Рамеш,

1

@ inulinux12, ви можете використовувати наступний forцикл рядка з командного рядка:

$ for dir in images2/*; do mv "$dir"/* "${dir/2/}"; done

Це перемістить всі файли з images2до imagesу відповідних каталогах. Примітка. Це передбачає, що жоден файл не має того самого імені.

Наприклад:

Перед виконанням:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2
images/adfoo:
jpg.7
images/fe:
jpg.5
images2:
ad  adfoo  fe
images2/ad:
jpg.3
images2/adfoo:
jpg.6
images2/fe:
jpg.4

Після виконання:

$ ls -R images*
images:
ad  adfoo  fe
images/ad:
jpg.1  jpg.2  jpg.3
images/adfoo:
jpg.6  jpg.7
images/fe:
jpg.4  jpg.5

3
Не розбирайте вихід ls. mywiki.wooledge.org/ParsingLs
Ітан Рейснер

@EtanReisner Дякую за пропозицію; Схоже, досить вузькі сценарії, хоча з огляду на інформацію, подану у питанні.
Simply_Me

2
@Simply_Me Хоча правда, що зазвичай це буде нормально, ви дійсно не хочете, щоб він вибухнув, коли ви потрапили у справу, на яку ви не розраховували. Це може спричинити по- справжньому погані проблеми. Не кажучи вже про те, що він досить часто (як у цьому випадку) майже тривіально замінюється простим глобусом. Дивіться мою відповідь як приклад цього.
Ітан Рейснер

@Simply_Me Сценарії включають імена файлів з пробілами, що досить часто зустрічається для зображень.
Жиль

@Gilles та @Etan Reisner, дякую за вклад, я ціную це! Оновлено та протестував мою відповідь на використання підстановки рядків, і це стало швидше, ніж використання basenameв цій конкретній ситуації (не потрібно закликати basenameдо цього). Ще раз дякую за конструктивні коментарі.
Simply_Me
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.