POSIXly, вы бы использовали paxв режиме чтения + записи с -lопцией:
pax -rwlpe -s /A/B/ dirA .
( -peсохраняет все возможные атрибуты файлов (в данном случае только каталоги), которые копируются, как cpэто -aделает GNU ).
Теперь, хотя и стандартная , эта команда не обязательно очень переносима .
Во-первых, многие системы на основе GNU / Linux не включают paxпо умолчанию (хотя это не дополнительная утилита POSIX).
Затем ряд ошибок и несоответствий с несколькими реализациями вызывают ряд проблем с этим кодом.
- из-за ошибки Solaris 10
pax(по крайней мере) не работает при использовании -rwlв сочетании с -s. По какой-то причине кажется, что применяется замена как к исходному, так и к скопированному пути. Так что выше, он будет пытаться сделать некоторые link("dirB/file", "dirB/file")вместо link("dirA/file", "dirB/file").
- во FreeBSD
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, проще всего сделать это следующим образом:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")
(который также будет работать вокруг большинства проблем, упомянутых выше, но потерпит неудачу, если абсолютный путь $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:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")
paxи во FreeBSD,cp -aне содержит жестких ссылок.