Відповіді:
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
(і є дуже ефективним IO, оскільки створюються лише покажчики, а фактичні дані не потрібно копіювати) Який із цих способів вирішення (якщо такий є) підходить, дуже залежатиме від конкретного випадку використання.
Як завжди, подумайте, перш ніж виконати будь-яку з цих команд, і створіть резервні копії.
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
вихід.
Ви можете скористатися -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: Схоже, може бути декілька аргументів ДЖЕРЕЛА, якщо вам це потрібно.
Ось спосіб, який об’єднає каталоги. Це набагато швидше, ніж rsync, оскільки він просто перейменовує файли, а не копіює їх та видаляє.
cd source; find -type f -print0 | xargs -0 -n 1 -I {} mv '{}' 'dest/{}'
dest
вже є каталог з тим самим іменем, що і в source
. І файли будуть переміщені в a dest
, який знаходиться в source
. Команда робить не що інше, якmv source/* source/dest/.
Одним із способів цього було б скористатися:
mv folder/* directory/folder/
rmdir folder
Поки немає двох файлів не мають таке ж ім'я в folder
і directory/folder
, ви досягнете того ж результату , тобто злиття.
rm folder
працює?
rm folder -fR
завжди працює для мене
Для найчистіших копій я використовую метод копіювання tar (-) B blockread.
Наприклад, з вихідного контуру ('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 / писати в 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 набагато швидше, оскільки він лише оновлює вставки, не копіюючи файли фізично. Кращим варіантом є використання файлового менеджера вашої операційної системи. Для програми «Відкриття» існує файловий менеджер під назвою Konquerer. Він може переміщувати файли, фактично не копіюючи їх. Він має функцію "вирізати та вставити", як у Windows. Просто виберіть усі підкаталоги в каталозі А. Клацніть правою кнопкою миші та перейдіть у каталог В, який може містити підкаталоги з однаковими назвами. Це їх об'єднає. Також є варіанти, чи потрібно перезаписувати або перейменувати файли з тим самим іменем.
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̲s̲t̲i̲n̲a̲t̲i̲o̲n̲ o̲n̲e̲ i̲s̲ n̲o̲t̲ e̲m̲pt̲y .
mv: не вдається перемістити '/ source / path / folder' to '/ target / target / folder': Каталог не порожній
Якщо папка призначення порожня, наведена вище команда спрацює нормально.
Отже, щоб об'єднати обидві папки у будь-якому випадку,
виконайте це у двох командах:
$ 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.