Como copiar um diretório recursivamente usando hardlinks para cada arquivo


52

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

Respostas:


50

No Linux (mais precisamente com o GNU e busyboximplementações cpnormalmente encontradas em sistemas que têm Linux como kernel) e no FreeBSD recente, é assim:

cp -al dirA dirB

Para uma solução mais portátil, consulte a resposta usando pax e cpio por Stéphane Chazelas


Observe que pax, como no FreeBSD, cp -anão vincula links simbólicos.
Stéphane Chazelas

Esteja ciente de que links físicos não funcionam em montagens de sistema de arquivos separadas.
Dave

24

POSIX, você usaria paxno modo de leitura + gravação com a -lopção:

pax -rwlpe -s /A/B/ dirA .

( -pePreserva todos os atributos possíveis de arquivos (neste caso apenas diretórios) que são copiados, como GNU cp's -afaz).

Agora, embora padrão , esse comando não é necessariamente muito portátil .

Primeiro, muitos sistemas baseados em GNU / Linux não os incluem paxpor 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 -rwlem 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, paxnã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 -> AAlink simbólico em dirA, ele se tornará foo -> BAno dirB.

Além disso, se você quiser fazer o mesmo, mas com caminhos de arquivo arbitrários cujo conteúdo é armazenado $srce $dst, é importante perceber que pax -rwl -- "$src" "$dst"cria toda a estrutura de diretórios do $srcinterior $dst(que precisa existir e ser um diretório). Por exemplo, se $srcfor foo/bar, então, $dst/foo/baré criado.

Se, em vez disso, você deseja $dstser 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 $dstterminasse em caracteres de nova linha).

Agora isso não ajuda em sistemas GNU / Linux onde não há pax.

É interessante notar que paxfoi criado pelo POSIX para mesclar os recursos dos comandos tare 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 -rwlseria cpio -pl. Contudo:

  1. 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)
  2. Todos os arquivos precisam ser especificados (normalmente você fornece a saída de find( finde cpioforam desenvolvidos em conjunto pelas mesmas pessoas)).
  3. os metadados não são preservados (algumas cpioimplementaçõ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")

Parece que -s / A / B / é específico para o meu exemplo. Como você faria isso se o nome do diretório de origem e o nome do diretório de destino fossem variáveis ​​$ sourcedir e $ targetdir?
Gudmundur Orn

@GudmundurOrn, veja editar.
Stéphane Chazelas

Eu executo este comando no OS X e recebo apenas uma mensagem de erro "pax: Não é possível vincular o arquivo ./a.txt a ele próprio". Eu usei o seu comando literalmente, apenas substituindo o diretório de origem pelo nome real, deixando / A / B e o ponto final como está. Estou entendendo mal alguma coisa?
db

@db, -s /A/Bsubstitui Apor Bpara que dirAse torne dirB. Se o nome do diretório de origem não tiver A, então ele será copiado (link) sobre ele mesmo. Veja também o restante da resposta para abordagens possivelmente melhores.
Stéphane Chazelas

6

Resposta curta:

cd $source_folder
pax -rwlpe . $dest_folder

2

Caso você esteja procurando esse recurso de cópia com hardlinks para fazer snapshots ou backups (total ou parcial) de seus arquivos, consulte rsnapshot.


11
Isso é interessante. Mas acho que os links físicos são apenas um bom mecanismo de captura instantânea se os arquivos não forem modificados. Direito?
Gudmundur Orn

@Gudmundur Orn; Isto está correto. A ferramenta mencionada na minha resposta criará um novo instantâneo de maneira que os arquivos sejam únicos; ou seja, arquivos existentes (não modificados) serão criados como links físicos e novos arquivos (ou versões modificadas de arquivos existentes) serão criados como novos arquivos. Portanto, em conseqüência, você terá a menor redundância.
Janis

0

A resposta de @ gudmundur-orn está correta, mas se você estiver no BtrFS no Linux, cp a --reflink=auto dirA dirBdeve 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 com cp -cum Mac com APFS ( autofará uma cópia completa, se não for possível, -cfalhará).

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.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.