Eu quero criar uma "cópia" de uma árvore de diretórios onde cada arquivo é um link direto para o arquivo original
Exemplo: Eu tenho uma estrutura de diretórios:
dirA/
dirA/file1
dirA/x/
dirA/x/file2
dirA/y/
dirA/y/file3
Aqui está o resultado esperado, uma "cópia" da árvore de diretórios em que cada arquivo é um link direto para o arquivo original:
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
, como no FreeBSD,cp -a
não vincula links simbólicos.POSIX, você usaria
pax
no modo de leitura + gravação com a-l
opção:(
-pe
Preserva todos os atributos possíveis de arquivos (neste caso apenas diretórios) que são copiados, como GNUcp
'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.
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 emlink("dirB/file", "dirB/file")
vez delink("dirA/file", "dirB/file")
.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á umfoo -> AA
link simbólico emdirA
, ele se tornaráfoo -> BA
nodirB
.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 quepax -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
forfoo/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:(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 comandostar
ecpio
.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 umapax
). 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
seriacpio -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)find
(find
ecpio
foram desenvolvidos em conjunto pelas mesmas pessoas)).cpio
implementações têm opções para preservar alguns, mas nada portátil).Então com
cpio
:fonte
-s /A/B
substituiA
porB
para quedirA
se tornedirB
. Se o nome do diretório de origem não tiverA
, então ele será copiado (link) sobre ele mesmo. Veja também o restante da resposta para abordagens possivelmente melhores.Resposta curta:
fonte
Caso você esteja procurando esse recurso de cópia com hardlinks para fazer snapshots ou backups (total ou parcial) de seus arquivos, consulte
rsnapshot
.fonte
A resposta de @ gudmundur-orn está correta, mas se você estiver no BtrFS no Linux,
cp a --reflink=auto dirA dirB
deve fazer o truque, com a diferença de que os arquivos são realmente diferentes e mudar um não muda o outro. Você pode conseguir o mesmo comcp -c
um Mac com APFS (auto
fará uma cópia completa, se não for possível,-c
falhará).Qualquer sistema de arquivos COW deve ser capaz de fazer isso, mas os fornecedores não concordaram com uma opção de linha de comando padrão.
fonte