Каков наилучший способ объединения двух каталогов в одной файловой системе в Linux?

Каков наилучший способ объединения двух каталогов в одной файловой системе в Linux?

У меня есть два каталога, которые нужно объединить. Файлы в этих двух каталогах все большие (>= 500 МБ).

Что я хочу архивировать: Для файлов в исходном каталоге: если их нет в целевом каталоге, mvто в целевой каталог (что быстро, поскольку мы по сути создаем новую жесткую ссылку и отменяем связь с исходным файлом); если они есть в целевом каталоге, то копируем туда исходный файл и удаляем исходный файл.

Наиболее распространенный способ объединения каталогов в системе Linux — использование опции rsyncwith --remove-source-files. Но это медленно, поскольку операция копирования будет выполнена даже если файл назначения не существует.

Есть идеи получше? Спасибо.

решение1

В основном то, что Вы описали, это перемещение файлов в место назначения перезаписи, если оно существует. Так что просто переместите их.

решение2

Есть случай, когда mvне удается. Вот некоторые примеры данных:

mkdir -p src/d dest/d
touch src/d/f1 dest/d/f2

Посмотрите, как это mvне удается:

$ mv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -f src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fv src/* dest/
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi src/* dest/
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty
$ mv -fvi -t dest/ src/*      
mv: overwrite 'dest/d'? y
mv: cannot move 'src/d' to 'dest/d': Directory not empty

Итак, создайте файл скрипта:

vim supermove

Этот пример не проверяет ошибки (ОТКАЗ ОТ ОТВЕТСТВЕННОСТИ: у меня работает, но, пожалуйста, проверьте, работает ли он у вас... возможно, с echobefore mv), и перезапишет файлы с тем же путем. И он использует find с, \;что ужасно неэффективно, но +не работает правильно с "$dest"prepended. Более старые версии будут создавать некоторые каталоги без пути, а более новые версии find выдадут:

find: In '-exec ... {} +' the '{}' must appear by itself, but you specified 'dest/{}'

Хотя, возможно, вы сможете найти способ исправить это с помощью xargs. (Это заняло несколько минут на файлах 64k и 8TB, которые я перемещал). Добавьте этот контент:

#!/bin/bash

src=$1
dest=$2

src=$(readlink -f "$src")
dest=$(readlink -f "$dest")

cd "$src"

# also copy hidden files
shopt -s dotglob

# make dirs (missing old permission,acl,xattr data), and then mv the files
time find * -type d -exec mkdir -p "$dest"/{} \;
time find * -type f -exec mv {} "$dest"/{} \;

# also copy permissions, acls, xattrs
rsync -aAX "$src"/ "$dest"/

И сделайте его исполняемым:

chmod +rx supermove

И запустите его.

./supermove src/ dest/

И результат... до:

$ find src dest
src/
src/d
src/d/f1
dest/
dest/d
dest/d/f2

После:

$ find src dest
src
src/d
dest
dest/d
dest/d/f1
dest/d/f2

Теперь src/должны быть только пустые директории. Если так, то можно rm -r srcпочистить.

решение3

mvВсе варианты направлены на разрешение конфликтов:

Выбери один:

-f  force (always overwrite)
-i  interactive (ask whether to overwrite)
-n  no clobber (no overwrite)

И это тоже хорошо:

-v  verbose

В противном случае данные могут потеряться и/или будет непонятно, что именно произошло.

mv также лучше на той же fs, потому что он просто обновляет inode каталога, файлы не должны портиться. Другое дело, что чем больше операция, тем больше вероятность, что что-то пойдет не так, например, возникнут программные ошибки.

Связанный контент