Відповіді:
mvне вдається об'єднати або перезаписати каталоги, це не вдасться з повідомленням "mv: не можна перемістити" a "до" b ": Каталог не порожній" , навіть якщо ви використовуєте цю --forceопцію.
Ви можете подолати це за допомогою інших інструментів (наприклад rsync, findабо навіть cp), але вам потрібно ретельно розглянути наслідки:
rsyncможна об'єднати вміст одного каталогу в інший (в ідеалі з опцією --remove-source-files1 безпечно видалити лише ті вихідні файли, які були успішно передані, і звичайним дозволом / правом власності / збереження часу, -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.