Слияние папок с mv?

Если я использую mv для перемещения папки с именем «папка» в каталог, который уже содержит «папку», они будут слияния или будут заменены?

114 голосов | спросил Dominique 3 Maypm14 2014, 22:41:34

9 ответов


88

mv не может объединять или перезаписывать каталоги, он не сгенерируется с сообщением "mv: невозможно переместить 'a' в 'b': Directory not empty" , даже если вы используете параметр --force.


Вы можете обойти это с помощью других инструментов (например, rsync, find или даже cp)), но вам нужно внимательно рассмотреть последствия:

  • rsync может объединить содержимое одного каталога в другое (в идеале с помощью опции --remove-source-files 1 ), чтобы безопасно удалить только те источники файлы, которые были успешно перенесены, и с обычным вариантом разрешения /сохранения /сохранения времени -a, если хотите)
    «, но , это полная операция копирования и поэтому может быть очень интенсивным для диска.
  • Вы можете использовать find для последовательного воссоздания структуры исходного каталога в целевом объекте, затем индивидуально переместить фактические файлы
    â € | , но , это должно повторяться через источник несколько раз и может столкнуться с условиями гонки (новые каталоги создаются у источника во время многоступенчатого процесса).
  • cp может создавать жесткие ссылки (просто добавьте дополнительные указатели в один и тот же существующий файл) , который создает результат, очень похожий на слияние mv (и очень эффективен для ввода-вывода, поскольку создаются только указатели, и фактические данные не нужно копировать)
    «, но это снова страдает от возможного состояния гонки (новые файлы в источнике удаляются, даже если они не были скопированы на предыдущем шаге).

Какой из этих обходных решений (если таковой имеется) подходит, будет очень сильно зависеть от вашего конкретного варианта использования.
Как всегда, подумайте, прежде чем выполнять какие-либо из этих команд и иметь резервные копии.


1: Обратите внимание, что rsync --remove-source-files не будет удалять каталоги, поэтому вам нужно будет сделать что-то вроде find -type d -empty -delete, чтобы избавиться от пустого каталога исходного каталога.

ответил n.st 3 Maypm14 2014, 22:47:04
70
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
ответил fazie 3 Maypm14 2014, 22:58:35
47

Вы можете использовать опцию -l команды cp , которая создает жесткие ссылки файлов в одной и той же файловой системе вместо полных копий данных. Следующая команда копирует папку source/folder в родительскую папку (destination), которая уже содержит каталог с именем folder.

cp -rl source/folder destination
rm -r source/folder

Вы также можете использовать -P (--no-dereference - не ссылаться на символические ссылки) или -a (--archive - сохранить все метаданные, также включает в себя опцию -P), в зависимости от ваших потребностей.

ответил palswim 10 WedEurope/Moscow2014-12-10T00:32:08+03:00Europe/Moscow12bEurope/MoscowWed, 10 Dec 2014 00:32:08 +0300 2014, 00:32:08
21

Я бы рекомендовал следующие четыре шага:

cd ${SOURCE}; 
find . -type d -exec mkdir -p ${DEST}/\{} \; 
find . -type f -exec mv \{} ${DEST}/\{} \; 
find . -type d -empty -delete

или еще лучше, вот скрипт, который реализует семантику, похожую на mv:

#!/bin/bash

DEST="${@:${#@}}"
ABS_DEST="$(cd "$(dirname "$DEST")"; pwd)/$(basename "$DEST")"

for SRC in ${@:1:$((${#@} -1))}; do   (
    cd "$SRC";
    find . -type d -exec mkdir -p "${ABS_DEST}"/\{} \;
    find . -type f -exec mv \{} "${ABS_DEST}"/\{} \;
    find . -type d -empty -delete
) done
ответил Jonathan Mayer 15 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowMon, 15 Sep 2014 09:33:27 +0400 2014, 09:33:27
15

Вот путь, который объединит каталоги. Это намного быстрее, чем rsync, поскольку он просто переименовывает файлы, а не копирует их, а затем удаляет их.

cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
ответил Jewel 5 thEurope/Moscowp30Europe/Moscow09bEurope/MoscowFri, 05 Sep 2014 08:48:45 +0400 2014, 08:48:45
3

Один из способов добиться этого - использовать:

mv folder/* directory/folder/
rmdir folder

Пока два файла не имеют одинакового имени в папке folder и directory/folder, вы достигнете того же результата, то есть слияния.

ответил asheeshr 4 Mayam14 2014, 07:39:02
1

Вот сценарий, который работал для меня. Я предпочитаю mv over rsync, поэтому я использую решения Jewel и Jonathan Mayer.

#!/bin/bash

# usage source1 .. sourceN dest

length=$(($#-1))
sources=${@:1:$length}
DEST=$(readlink -f ${!#})
for SRC in $sources; do
    pushd $SRC;
    find . -type d -exec mkdir -p ${DEST}/{} \;
    find . -type f -exec mv {} ${DEST}/{} \;
    find . -type d -empty -delete
    popd
done
ответил xer0x 29 62014vEurope/Moscow11bEurope/MoscowSat, 29 Nov 2014 23:13:32 +0300 2014, 23:13:32
1

Не рекомендуется использовать такие команды, как cp или rsync. Для больших файлов это займет много времени. mv намного быстрее, так как он только обновляет индексные дескрипторы, не копируя файлы физически. Лучшим вариантом является использование файлового менеджера вашей операционной системы. Для Opensuse есть файловый менеджер под названием Konquerer. Он может перемещать файлы, не копируя их. Он имеет функцию «вырезать и вставлять», как в Windows. Просто выберите все подкаталоги в каталоге A. Щелкните правой кнопкой мыши и перейдите в каталог B, который может содержать подкаталоги с одинаковыми именами. Он объединит их. Также есть варианты, хотите ли вы перезаписать или переименовать файлы с тем же именем.

ответил simon 26 FebruaryEurope/MoscowbFri, 26 Feb 2016 16:43:11 +0300000000pmFri, 26 Feb 2016 16:43:11 +030016 2016, 16:43:11
1

Для самых чистых копий, я использую метод copy-to-tar (-) B.

пример, из исходного пути:

tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)

это создает точную копию исходного дерева, с владельцем и разрешениями нетронутыми. И если целевая папка существует, данные будут объединены. Только файлы, которые уже существуют, будут перезаписаны.

Когда действие копирования будет успешным, вы можете удалить источник (rm -rf <source>). Конечно, это не точный ход: данные будут скопированы, пока вы не удалите источник.

В качестве опции вы можете быть подробным (отображать на экране копируемый файл), с -v: tar cBvf -

  • c: создать
  • B: прочитать полный блок (для чтения канала)
  • v: verbose
  • f: файл для записи
  • x: extract
  • -: stdout /stdin

sourcefolder также может быть * (для чего-либо в текущей папке)

ответил gjs 26 J0000006Europe/Moscow 2017, 17:49:55

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132