POSIXly, você usaria pax
no modo de leitura + gravação com a opção -l
:
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 o cp
do GNU -a
).
Agora, embora padrão , esse comando não é necessariamente muito portátil .
Primeiro, muitos sistemas baseados em GNU / Linux não 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.
- devido a um erro, o Solaris 10
pax
(pelo menos) não funciona ao usar -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 link("dirB/file", "dirB/file")
em vez de link("dirA/file", "dirB/file")
.
- no FreeBSD,
pax
não cria hardlinks para arquivos do tipo symlink (um comportamento permitido pelo POSIX). Não só isso, mas também aplica a substituição aos alvos dos links simbólicos (um comportamento não permitido pelo POSIX). Por exemplo, se houver um link simbólico foo -> AA
em dirA
, ele se tornará foo -> BA
em dirB
.
Além disso, se você quiser fazer o mesmo, mas com caminhos de arquivo arbitrários cujo conteúdo é armazenado em $src
e $dst
, é importante perceber que pax -rwl -- "$src" "$dst"
cria a estrutura de diretório completa de $src
inside $dst
(que tem que existir e ser um diretório). Por exemplo, se $src
for foo/bar
, então, $dst/foo/bar
será criado.
Se, em vez disso, você quiser que $dst
seja uma cópia de $src
, é mais fácil fazer isso como:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && pax -rwlpe . "$absolute_dst")
(que também funcionaria em torno da maioria dos problemas mencionados acima, mas falharia se o caminho absoluto de $dst
terminasse em caracteres de nova linha).
Agora, isso não ajudará nos 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 Unix (de 1977) em oposição a uma invenção POSIX, e há também uma implementação GNU (não é pax
one). Portanto, mesmo que não seja mais um comando padrão (era no SUSv2), ainda é muito comum e há um conjunto principal de recursos em que você pode confiar normalmente.
O equivalente a pax -rwl
seria cpio -pl
. No entanto:
-
cpio
pega a lista do arquivo de entrada em stdin, ao contrário dos argumentos (delimitada 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 algumas, mas nada portáveis).
Então, com cpio
:
absolute_dst=$(umask 077 && mkdir -p -- "$dst" && cd -P -- "$dst" && pwd -P) &&
(cd -P -- "$src" && find . | cpio -pl "$absolute_dst")