Я хочу создать «копию» дерева каталогов, где каждый файл является жесткой ссылкой на исходный файл
Пример: у меня есть структура каталогов:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
Вот ожидаемый результат, «копия» дерева каталогов, где каждый файл является жесткой ссылкой на исходный файл:
dirB/ # normal directory
dirB/file1 # hardlink to dirA/file1
dirB/x/ # normal directory
dirB/x/file2 # hardlink to dirA/x/file2
dirB/y/ # normal directory
dirB/y/file3 # hardlink to dirA/y/file3
pax
и во FreeBSD,cp -a
не содержит жестких ссылок.POSIXly, вы бы использовали
pax
в режиме чтения + записи с-l
опцией:(
-pe
сохраняет все возможные атрибуты файлов (в данном случае только каталоги), которые копируются, какcp
это-a
делает GNU ).Теперь, хотя и стандартная , эта команда не обязательно очень переносима .
Во-первых, многие системы на основе GNU / Linux не включают
pax
по умолчанию (хотя это не дополнительная утилита POSIX).Затем ряд ошибок и несоответствий с несколькими реализациями вызывают ряд проблем с этим кодом.
pax
(по крайней мере) не работает при использовании-rwl
в сочетании с-s
. По какой-то причине кажется, что применяется замена как к исходному, так и к скопированному пути. Так что выше, он будет пытаться сделать некоторыеlink("dirB/file", "dirB/file")
вместоlink("dirA/file", "dirB/file")
.pax
не создает жестких ссылок для файлов типа symlink (поведение, разрешенное POSIX). Кроме того, он также применяет подстановку к целям символических ссылок (поведение, не допускаемое POSIX). Так, например, если естьfoo -> AA
символическая ссылкаdirA
, она станетfoo -> BA
внутриdirB
.Кроме того, если вы хотите сделать то же самое, но с произвольными путями к файлам, содержимое которых хранится в
$src
и$dst
, важно понимать, чтоpax -rwl -- "$src" "$dst"
создает полную структуру каталогов$src
внутри$dst
(которая должна существовать и быть каталогом). Например, если$src
естьfoo/bar
, то$dst/foo/bar
создается.Если вместо этого вы хотите
$dst
быть копией$src
, проще всего сделать это следующим образом:(который также будет работать вокруг большинства проблем, упомянутых выше, но потерпит неудачу, если абсолютный путь
$dst
оканчивается символами новой строки).Теперь это не поможет в системах GNU / Linux, где их нет
pax
.Интересно отметить , что
pax
была создана POSIX для слияния в себе чертыtar
иcpio
команд.cpio
является исторической командой Unix (с 1977 года), в отличие от изобретения POSIX, и есть реализация GNU (а неpax
одна). Таким образом, даже если это больше не стандартная команда (хотя она была в SUSv2), она все еще очень распространена, и есть основной набор функций, на которые вы обычно можете положиться.Эквивалент
pax -rwl
будетcpio -pl
. Тем не мение:cpio
принимает список входного файла в stdin, в отличие от аргументов (разделитель новой строки, что означает, что имена файлов с символами новой строки не поддерживаются)find
(find
иcpio
были разработаны совместно теми же людьми)).cpio
реализации имеют опции для сохранения некоторых, но ничего переносимого).Так что с
cpio
:источник
-s /A/B
заменяетсяA
наB
так, чтоdirA
становитсяdirB
. Если имя вашего исходного каталога не имеетA
, тогда это скопирует (свяжет) это по себе. Смотрите также остальную часть ответа для возможных лучших подходов.Краткий ответ:
источник
В случае, если вы ищете эту функцию копирования с жесткими ссылками для создания снимков или резервных копий (полностью или частично) ваших файлов
rsnapshot
.источник
Ответ @ gudmundur-orn верен, но если вы работаете в BtrFS в Linux, вам
cp a --reflink=auto dirA dirB
нужно сделать то же самое, с той разницей, что файлы на самом деле разные, и изменение одного не меняет другого. Вы можете добиться в основном того же сcp -c
Mac на APFS (auto
полная копия будет сделана, если это невозможно,-c
не удастся).Любая файловая система COW должна быть в состоянии сделать это, но производители не согласовали стандартную опцию командной строки.
источник