Иногда у меня есть два дерева, которые раньше имели одинаковый контент, но выросли не синхронно (потому что я перемещал диски или что-то еще). Хорошим примером является дерево, в котором я зеркалирую исходные пакеты Fedora.
Я хочу снова объединить эти два дерева, переместив все файлы из tree1 в tree2.
Обычно я делаю это с помощью:
rsync -arv tree1/* tree2
Затем удалите tree1.
Однако на это уходит очень много времени и места на диске, и было бы гораздо проще сделать:
mv -r tree1/* tree2
Другими словами, рекурсивный ход. Это было бы быстрее, потому что, во-первых, он даже не копировал бы, просто перемещал inodes, а во-вторых, мне не нужно было бы удалять в конце.
Это существует?
В качестве тестового примера рассмотрим следующую последовательность команд:
$ mkdir -p a/b
$ touch a/b/c1
$ rsync -arv a/ a2
sending incremental file list
created directory
./
b/
b/c1
b/c2
sent 173 bytes received 57 bytes 460.00 bytes/sec
total size is 0 speedup is 0.00
$ touch a/b/c2
Какая команда теперь будет иметь эффект перемещения a / b / c2 в a2 / b / c2 с последующим удалением поддерева a (поскольку все в нем уже находится в дереве назначения)?
предлагаемый mv -uf dir1/* dir2/
перемещайте (под) каталоги, а не каждый файл. вы можете попробовать использовать find
cd dir1
find . -type d -exec mkdir -p dir2/"{}" \;
find . -type f -exec mv -uf "{}" dir2/"{}" \;
или что-то подобное
Согласно справочной странице mv (1) от GNU mv
:
-u, --update
move only when the SOURCE file is newer than the destination
file or when the destination file is missing
Не
mv -uf tree1/* tree2/
работай?
Midnight Commander (mc) тоже хорош для такого рода вещей. Пометьте файлы с помощью CTRL-t, нажмите F6, и когда он попросит перезаписать целевые файлы, выберите «Обновить», если вы хотите перезаписать старые файлы.
Вы можете использовать "cp -l & rm" для перемещения внутри устройства:
cp -alv --backup=numbered tree1/* tree2 &&
rm -rf tree1/
-l
из cp
использовать жесткие ссылки вместо копирования (это также предотвращает операции между устройствами)--backup=numbered
из cp
для резервного копирования существующих файлов в целевом каталогеИ будьте осторожны с этими двумя проблемами:
&&
чтобы предотвратить удаление ваших нескопированных данных, если вы случайно запустите его на разных устройствах. (в корпусе корсса cp
выходит со статусом "1
", по крайней мере, для GNU coreutils).
" в tree1
, вы потеряете их, если они есть.Ответ Хавьера с помощью find работает хорошо, за исключением того, что он не удаляет исходные каталоги. Добавьте в конце:
rmdir $(find . -type d |grep -v ^\.$)
ошибаться
mv dir1/* dir2/
или просто
rsync -arv --remove-source-files tree1/* tree2
должно быть достаточно, вы, вероятно, столкнетесь с проблемами в какой-то момент, когда слишком много записей в dir1
.
find sourcedir -maxdepth 1 -exec echo mv {} targetdir/ \;
должны быть хорошие варианты
find sourcedir -maxdepth 1 -print0 |xargs -0 -I _ echo mv _ targetdir
find sourcedir -maxdepth1 -exec mv {} targetdir/ +
оба на самом деле не нужны, потому что mv просто принимает 2 варианта (исходная цель), поэтому в этом случае вам придется жить с множеством процессов.
cd /tree1
mv * /tree2
Это не будет перемещать скрытые файлы или папки, но и ваш исходный пример тоже.
Я думаю, МВ не делает то, что ты думаешь.
Файловая система unix состоит из 3 компонентов:
Запись каталога указывает на индексный дескриптор.
В индексном дескрипторе есть метатаданные о файле (это файл, каталог, именованный канал? Кто им владеет? Какие разрешения? Какие блоки использует этот индексный дескриптор?
Блоки - это вещи, которые фактически содержат содержимое файла.
Итак - когда вы "mv" файл, все, что вы на самом деле делаете, это отсоединяете первую запись каталога и повторно связываете ее в другом месте.
snoopy -> inode 333
woodstock -> inode 333
Никакие данные никогда не дублируются / копируются. Вы создаете ссылку snoopy, затем вы создаете ссылку woodstock, а затем удаляете ссылку snoopy. (с каталогами дела обстоят немного иначе, потому что обычно вы не можете создавать каталоги с жесткой связью, но даже в этом случае имя "ссылки" просто меняется).
Что делать, если вы переходите с одной файловой системы на другую? Раньше mv просто выдавал ошибку и явно указывал, что вы не можете переместить файл из одной файловой системы в другую. В эти дни кажется, что я тихо копии данные затем удаляют оригинал.
Раньше, поскольку вы не могли перемещать данные из одной файловой системы в другую, вы привыкли использовать идиомы вроде
tar -cf -. | (cd / new / location && tar -xf -)
затем вы удаляете старые данные. Отчасти причиной использования tar было то, что раньше cp уничтожал такие метаданные, как «это символическая ссылка» и «это жесткая ссылка», и вместо этого вы просто получали бы новые копии этого файла как обычные файлы. Тем не менее, вам нужно указать флаги «cp», чтобы сообщить ему, чтобы он сохранял такую структуру.
Невозможно избежать «перемещения» большого количества данных из одной файловой системы в другую. Неважно, используете ли вы новый ход, rsync, tar или cpio.
Но если вы храните все данные в одной файловой системе, это:
mv / файловая система-1 / большой / каталог * / файловая система-1 / большой2 /
это будет очень быстро, потому что это просто изменяет записи каталога, а не перемещает реальные данные.
Возникают и другие проблемы, например, что делать, если файл / каталог уже существует в новом месте, а также в исходном местоположении?
переключитесь в каталог, который хотите переместить, и выполните
tar cf - * | ( cd /target; tar xfp -)
Быстрее, чем мв ...