Как скопировать-объединить две директории?


112

У меня есть две директории images и images2 с этой структурой в Linux:

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

... и другие 4000 папок

а другой как:

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

... и другие 4000 папок

Каждая из этих папок содержит изображения, а имена каталогов под изображениями и изображениями2 одинаковы, однако их содержимое различно. Затем я хочу узнать, как я могу скопировать и объединить изображения / images2 / ad в images / ad, изображения / images2 / foo в images / 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.

Если вы хотите переместить файлы из /images2rsync, вы можете передать эту опцию --remove-source-files. Затем rsync копирует все файлы по очереди и удаляет каждый файл, когда это будет сделано. Это намного медленнее, чем перемещение, если каталоги источника и назначения находятся в одной файловой системе.


14
..добавить -P, если вы хотите увидеть прогресс ..
— Meetai.com

1
Я хотел бы добавить , что нет никакой пользы , используя хитрую петлю оболочки здесь , даже если вы действительно хотите , чтобы переместить их вместо того , чтобы копировать их-в этом случае просто использовать rsync, а затем rm -r /images.
— Уайлдкарт

1
Я также хотел бы отметить, что важно включать конечные слеши для каждого каталога . Например, если вы просто запустили rsync -a images images2, он просто скопирует images2 в изображения, а не объединит их.
— Кайл Чаллис

1
@ s3cur3 Ох. От 2 до (неявно) 1. Это не интуитивно понятно. Спасибо, я исправил свой ответ.
— Жиль

1
@MaxCoplan Нет. Rsync не является интерактивным инструментом.
— Жиль

43

Лучший выбор, как уже было сказано, это, конечно, rsync. Тем не менее, унисон будет отличным программным обеспечением для этой работы. Оба могут использоваться в нескольких операционных системах.

Rsync

rsync синхронизируется в одном направлении от источника к месту назначения. Поэтому следующее утверждение

rsync -avh --progress Source Destination

синхронизирует все от источника до места назначения . Объединенная папка находится в пункте назначения .

-a означает «архив» и рекурсивно копирует все из источника в место назначения, сохраняя почти все.

-v дает больше выходных данных ("подробный").

-ч для человека читабельно.

- прогресс, чтобы показать, сколько работы сделано.

Если вы хотите только обновить в целевую папку с новыми файлами из исходной папки:

rsync -avhu --progress source destination

унисон

унисон синхронизируется в обоих направлениях. Поэтому следующее утверждение

unison Source Destination

синхронизирует обе директории в обоих направлениях и, наконец, источник равен месту назначения. Это все равно что дважды выполнять rsync от источника к месту назначения и наоборот.

Для более продвинутого использования посмотрите справочные страницы или следующие веб-сайты:

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

2
Я хочу упомянуть, что правильный путь к папке должен быть с косой чертой в конце rsync -avh --progress source/ destination/, иначе исходная папка будет создана в папке назначения, по крайней мере, в моем случае, как это было.
— Electroid

Это прекрасно работает для меня (с косой чертой в папках). Спасибо!
— Леопольдо Санчик

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.