POSIX, você usaria pax
no modo de leitura + gravação com a -l
opção:
pax -rwlpe -s /A/B/ dirA .
( -pe
Preserva todos os atributos possíveis de arquivos (neste caso apenas diretórios) que são copiados, como GNU cp
's -a
faz).
Agora, embora padrão , esse comando não é necessariamente muito portátil .
Primeiro, muitos sistemas baseados em GNU / Linux não os incluem pax
por padrão (mesmo que seja um utilitário POSIX não opcional).
Em seguida, vários bugs e não conformidades com algumas implementações causam vários problemas com esse código.
- por causa de um erro, o Solaris 10
pax
(pelo menos) não funciona quando usado -rwl
em combinação com -s
. Por alguma razão, parece que aplica a substituição ao caminho original e copiado. Então, acima, ele tentaria fazer alguns em link("dirB/file", "dirB/file")
vez de link("dirA/file", "dirB/file")
.
- no FreeBSD,
pax
não cria hardlinks para arquivos do tipo link simbólico (um comportamento permitido pelo POSIX). Não apenas isso, mas também aplica a substituição aos destinos dos links simbólicos (um comportamento não permitido pelo POSIX). Assim, por exemplo, se há um foo -> AA
link simbólico em dirA
, ele se tornará foo -> BA
no dirB
.
Além disso, se você quiser fazer o mesmo, mas com caminhos de arquivo arbitrários cujo conteúdo é armazenado $src
e $dst
, é importante perceber que pax -rwl -- "$src" "$dst"
cria toda a estrutura de diretórios do $src
interior $dst
(que precisa existir e ser um diretório). Por exemplo, se $src
for foo/bar
, então, $dst/foo/bar
é criado.
Se, em vez disso, você deseja $dst
ser uma cópia $src
, o mais fácil é provavelmente fazê-lo como:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")
(que também solucionaria a maioria dos problemas mencionados acima, mas falharia se o caminho absoluto de $dst
terminasse em caracteres de nova linha).
Agora isso não ajuda em sistemas GNU / Linux onde não há pax
.
É interessante notar que pax
foi criado pelo POSIX para mesclar os recursos dos comandos tar
e cpio
.
cpio
é um comando histórico do Unix (de 1977) em oposição a uma invenção POSIX, e também existe uma implementação do GNU (não uma pax
). Portanto, mesmo que não seja mais um comando padrão (era no SUSv2), ainda é muito comum, e há um conjunto principal de recursos nos quais você geralmente pode confiar.
O equivalente a pax -rwl
seria cpio -pl
. Contudo:
cpio
pega a lista de arquivos de entrada no stdin em vez de argumentos (delimitado por nova linha, o que significa que os nomes de arquivo com caracteres de nova linha não são suportados)
- Todos os arquivos precisam ser especificados (normalmente você fornece a saída de
find
( find
e cpio
foram desenvolvidos em conjunto pelas mesmas pessoas)).
- os metadados não são preservados (algumas
cpio
implementações têm opções para preservar alguns, mas nada portátil).
Então com cpio
:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")
pax
, como no FreeBSD,cp -a
não vincula links simbólicos.