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
не содержит жестких ссылок.