Ответы:
mv
не может объединить или перезаписать каталоги, произойдет сбой с сообщением «mv: не может переместить« a »в« b »: каталог не пустой» , даже если вы используете эту --force
опцию.
Вы можете обойти это, используя другие инструменты (например rsync
, find
или даже cp
), но вам нужно тщательно рассмотреть последствия:
rsync
может объединить содержимое одного каталога в другой (в идеале с опцией --remove-source-files
1 можно безопасно удалить только те исходные файлы, которые были успешно переданы, и с обычным вариантом разрешения / владения / сохранения времени, -a
если вы хотите) rsync
«s --link-dest=DIR
варианта (чтобы создать жесткие ссылки вместо копирования содержимого файла, где это возможно) и , --remove-source-files
чтобы получить семантическую очень похожи на обычный mv
. --link-dest
должен быть указан абсолютный путь к исходному каталогу (или относительный путь от места назначения к источнику ). --link-dest
непреднамеренным образом (что может или не может вызывать осложнения), требует знания (или определения) абсолютного пути к источнику (в качестве аргумента --link-dest
) и снова оставляет пустую структуру каталогов для очистки как за 1 .find
чтобы последовательно воссоздать исходную структуру каталогов на цели, затем индивидуально переместить фактические файлы cp
может создавать жесткие ссылки (проще говоря, дополнительные указатели на тот же существующий файл), что создает результат, очень похожий на слияние mv
(и очень эффективный с точки зрения ввода-вывода, так как создаются только указатели и никакие фактические данные не должны копироваться) Какой из этих обходных путей (если таковой имеется) является подходящим, во многом зависит от вашего конкретного варианта использования.
Как всегда, подумайте, прежде чем выполнять какую-либо из этих команд, и сделайте резервные копии.
1: Обратите внимание, что rsync --remove-source-files
никакие каталоги не будут удалены, поэтому вам нужно будет сделать что-то подобное find -depth -type d -empty -delete
потом, чтобы избавиться от пустого дерева каталогов исходного кода.
mv
реализацию используемого Debian - акцент быть на попробовал , так как страница руководство не упоминает это поведение ...
--delete
удаляются только файлы в целевом каталоге, которые не существуют в исходном каталоге.
-H
функции или вы можете жестко связать файлы в месте назначения, используя --link-dest
. Посмотрите справочную страницу, прежде чем их использовать.
rsync -av /source/ /destination/
(after checking)
rm -rf /source/
--remove-source-files
имеет преимущество удаления только тех файлов, которые были успешно переданы, так что вы можете использовать их find
для удаления пустых каталогов, и у вас останется все, что не было передано без проверки rsync
вывода s.
Вы можете использовать -l
опцию команды cp , которая создает жесткие ссылки на файлы в одной файловой системе вместо полных копий данных. Следующая команда копирует папку source/folder
в родительскую папку ( destination
), которая уже содержит каталог с именем folder
.
cp -rl source/folder destination
rm -r source/folder
Вы также можете использовать -P
( --no-dereference
- не отменять ссылки на символические ссылки) или -a
( --archive
- сохранить все метаданные, включая -P
опцию), в зависимости от ваших потребностей.
cp
вместо того , rsync
так как каждая система имеет cp
и каждый имеет знакомство с ним.
cp
со временем операции mv
.
-n
mv /fs1/file /fs2/
(через файловые системы) выполнит копирование, а затем удаление.
mv
будет работать (при условии, что целевой каталог еще не существует), даже если не "эффективно" или как вы его называете, cp -rl
потерпит неудачу.
Я бы порекомендовал эти четыре шага:
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
rsync -u
(только обновление, если новее), mv
(по крайней мере , в некоторых версиях) также можете воспользоваться этой -u
опцией. Однако в этом случае вы можете удалить непустые исходные каталоги, а также пустые каталоги, чтобы охватить случаи, когда файлы в исходном дереве не новее. @schuess: похоже, что может быть несколько аргументов SOURCE, если вам это нужно.
Вот способ слияния каталогов. Это намного быстрее, чем rsync, поскольку он просто переименовывает файлы, а не копирует их, а затем удаляет их.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
уже является каталогом с тем же именем, что и в source
. И файлы будут перемещены в папку dest
, которая находится в source
. Команда не делает ничего, кроме какmv source/* source/dest/.
Один из способов сделать это - использовать:
mv folder/* directory/folder/
rmdir folder
Пока нет двух файлов с одинаковыми именами в folder
и directory/folder
, вы получите тот же результат, то есть слияние.
rm folder
работает?
rm folder -fR
у меня всегда работает
Для самых чистых копий я использую метод блок-копии tar (-) B.
Например, из исходного пути (там, где это необходимо, 'cd'):
tar cBf - <sourcefolder> | (cd /your/target/folder ; tar xBf -)
это создает точную копию исходного дерева, с владельцем и разрешениями нетронутыми. И если целевая папка существует, данные будут объединены. Только файлы, которые уже существуют, будут перезаписаны.
Пример:
$ cd /data1/home
$ tar cBf - jdoe | (cd /data2/home ; tar xBf -)
Когда действие копирования выполнено успешно, вы можете удалить источник ( rm -rf <source>
). Конечно, это не точный ход: данные будут копироваться до тех пор, пока вы не удалите источник.
В качестве опции вы можете быть многословным (отобразить на экране копируемый файл), используя -v: tar cBvf -
c
: СоздайтеB
: прочитать полный блок (для чтения канала)v
: подробныйf
: файл для записиx
: извлечение-
: stdout / stdinsourcefolder
также может быть *
(для чего-либо в текущей папке)
f -
tar обычно не нужно - по умолчанию это чтение из stdin / write в stdout.
Вот сценарий, который работал для меня. Я предпочитаю mv, чем 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
Не рекомендуется использовать такие команды, как cp или rsync. Для больших файлов это займет много времени. mv намного быстрее, так как он только обновляет inode без физического копирования файлов. Лучшим вариантом является использование файлового менеджера вашей операционной системы. Для Opensuse существует файловый менеджер Konquerer. Он может перемещать файлы без их фактического копирования. Он имеет функцию «вырезать и вставить», как в Windows. Просто выберите все подкаталоги в каталоге A. Щелкните правой кнопкой мыши и перейдите в каталог B, который может содержать подкаталоги с одинаковыми именами. Это объединит их. Есть также варианты, хотите ли вы перезаписать или переименовать файлы с тем же именем.
mv
используется.
Решение Python
Так как я не мог найти удовлетворительное уже существующее решение, я решил сделать быстрый скрипт на Python для его достижения.
В частности, этот метод эффективен, поскольку он перемещается по дереву исходного файла только один раз снизу вверх.
Это также позволит вам быстро настроить такие вещи, как обработка перезаписи файлов по своему вкусу.
Использование:
move-merge-dirs src/ dest/
переместит все содержимое src/*
в dest/
и src/
исчезнет.
въезд слияние-каталоги
#!/usr/bin/env python3
import argparse
import os
def move_merge_dirs(source_root, dest_root):
for path, dirs, files in os.walk(source_root, topdown=False):
dest_dir = os.path.join(
dest_root,
os.path.relpath(path, source_root)
)
if not os.path.exists(dest_dir):
os.makedirs(dest_dir)
for filename in files:
os.rename(
os.path.join(path, filename),
os.path.join(dest_dir, filename)
)
for dirname in dirs:
os.rmdir(os.path.join(path, dirname))
os.rmdir(source_root)
if __name__ == '__main__':
parser = argparse.ArgumentParser(
description='Move merge src/* into dest. Overwrite existing files.'
)
parser.add_argument('src_dir')
parser.add_argument('dest_dir')
args = parser.parse_args()
move_merge_dirs(args.src_dir, args.dest_dir)
Смотрите также: https://stackoverflow.com/questions/22588225/how-do-you-merge-two-directories-or-move-with-replace-from-the-windows-command
Это команда для перемещения файлов и папок в другое место назначения:
$ mv /source/path/folder /target/destination/
Помните : mv
команда не будет работать, если папка b̲e̲i̲n̲g m̲e̲r̲ge̲d̲ (то есть другая папка с таким же именем уже существует в месте назначения) и d )e ands̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲y .
mv: невозможно переместить «/ source / path / folder» в «/ target / destination / folder»: каталог не пуст
Если папка назначения пуста, вышеуказанная команда будет работать нормально.
Итак, чтобы объединить обе папки в любом случае,
либо сделайте это в 2 команды:
$ cp -rf /source/path/folder /target/destination/
$ rm -rf /source/path/folder
Или объедините оба в одноразовую команду:
$ cp -rf /source/path/folder /target/destination/ && rm -rf /source/path/folder
mv = переместить
cp = копировать
rm = удалить-r для каталога (папки)
-f принудительное выполнение
mv
. Этот ответ был бы лучше с более широкой правдой. Linux, BSD и «настоящий» Unix, или ссылка от POSIX или SUS.