Вопрос или проблема
Мне нужно скопировать дерево каталогов, полное символических ссылок на файлы, на другой раздел, но в каталоге есть 2 или 3 символические ссылки на каталоги за пределами дерева копирования. Мне нужно скопировать символические ссылки, указывающие на файлы, как реальные файлы, но сохранить 2 или 3 символические ссылки на каталоги как символические ссылки.
scp -L
перенаправляет все
Я пробовал rsync -avHS
, а затем rsync -avHS --keep-dirlinks
или rsync -avHS -K
, но они сохраняют как ссылки на файлы, так и на каталоги на конечной стороне, так что в итоге ничего не перенаправляется.
Вы могли бы использовать функцию Python shutil.copytree
с параметром symlink
установленным в False и параметром ignore
установленным на функцию, которая проверяет, является ли каталог символической ссылкой (os.path.islink()
) и если нет, возвращает пустой список, но если это так, добавляет каталог и его цель (os.readlink
) как кортеж в список не следуемых символических ссылок для последующего восстановления и возвращает полный список содержимого (игнорируя всех потомков символической ссылки). Затем вы могли бы использовать список кортежей не следуемых символических ссылок и os.symlink
для создания конечных ссылок.
Скорее всего, в вашей Linux-дистрибуции Python уже установлен.
Вот Perl-скрипт из 2005 года, “Наведение порядка в беспорядке символических ссылок”, написанный известным Perl-хакером Рэндаллом Шварцем.
Конечно, он не делает точно то, что вам нужно, но содержит подробные построчные объяснения. Возможно, вы сможете адаптировать его под свои нужды.
.
Ответ или решение
Если вы ищете способ скопировать дерево каталогов в Linux с сохранением символических ссылок (symlinks) на каталоги, но разыменованием символических ссылок на файлы, у вас есть несколько путей решений. Давайте рассмотрим задачу детально и предоставим возможные подходы.
Теория
Стандартные UNIX-утилиты, такие как scp
и rsync
, предлагают весьма гибкие опции копирования, однако они предусматривают либо полное разыменование всех символических ссылок, либо сохранение их без изменений. Когда вы используете scp -L
, все ссылки разыменовываются без исключения. Аналогично, использование rsync
с флагами -avHS
совместно с --keep-dirlinks
или -K
приводит к сохранению всех ссылок, включая ссылки на файлы и каталоги.
Пример
Одна из возможных реализаций – более тонкий подход с использованием Python и его библиотеки shutil
. В рамках этой библиотеки функция shutil.copytree
может быть адаптирована для удовлетворения ваших требований. Вы можете скопировать файлы, игнорируя символические ссылки на каталоги, а затем вручную воссоздать сами ссылки.
import os
import shutil
def copydir_with_symlinks(src, dst):
symlinks_to_dirs = []
def ignore_func(dir, contents):
ignored = []
for item in contents:
path = os.path.join(dir, item)
if os.path.islink(path) and os.path.isdir(path):
symlinks_to_dirs.append((item, os.readlink(path)))
ignored.append(item)
return ignored
shutil.copytree(src, dst, symlinks=False, ignore=ignore_func)
# Recreate symlinks to directories
for target, linkname in symlinks_to_dirs:
os.symlink(linkname, os.path.join(dst, target))
# Использование функции
source_directory = '/path/to/source'
destination_directory = '/path/to/destination'
copydir_with_symlinks(source_directory, destination_directory)
Применение
Сначала функция ignore_func
определяет символические ссылки на каталоги и игнорирует их содержимое при копировании с помощью shutil.copytree
. После выполнения основной копии, функция воссоздает сохранённые символические ссылки для директорий в целевой директории.
Общий протокол работы заключается в определении и сохранении всех символических ссылок на каталоги для последующего восстановления. Это позволяет удовлетворить требование: разыменовать ссылки на файлы, сохраняя при этом ссылки на каталоги.
Если вам более привычен Perl, вы можете рассмотреть возможность адаптации предлагаемого скрипта Рэндалла Шварца из статьи "Cleaning up a symlink mess" для ваших нужд.
Эти решения помогут вам справиться с задачей и учесть все тонкости работы с символическими ссылками в Linux, сохраняя высокие стандарты профессиональной работы.