Como copiar uma estrutura de pastas e criar links simbólicos para arquivos?

21

Eu tenho uma pasta SOURCE que contém várias pastas de subnível, cada uma com seus próprios arquivos.

Quero copiar esta pasta em uma nova pasta COPY, na qual preciso copiar a estrutura de diretórios, mas manter os arquivos como links simbólicos para os arquivos originais em SOURCE e suas subpastas.

Antonello
fonte
1
Consulte também stackoverflow.com/q/1240636/905686 .
user905686
O GNU Stow meio que faz isso.
Kusalananda

Respostas:

27

Aqui está a solução no Linux não incorporado e Cygwin:

cp -as SOURCE/ COPY

Observe que SOURCE deve ser um caminho absoluto e ter uma barra final. Se você deseja fornecer um caminho relativo, pode usar

cp -as "$(pwd)/SOURCE/" COPY
roaima
fonte
Funciona perfeito, obrigado. Apenas uma nota .. fonte tem que ser administrado com caminho completo (COPY em vez disso pode ser dada em termos relativos se se deseja)
Antonello
Como fazê-lo funcionar se o diretório de origem for atualizado constantemente com novas pastas e novos arquivos dentro deles? Os links simbólicos para eles serão criados automaticamente no diretório de destino na estrutura de pastas correta?
SexyBeast
@AttitudeMonger Não, um comando como o cp cria os links apenas uma vez (como você pode ver no resultado). Para atualizar o destino automaticamente, você teria que monitorar o diretório de origem para alterações.
user905686
Isso pode ser feito para criar links relativos?
Ctrl-alt-delor 28/10/16
@ Richard se SOURCE é um caminho relativo, então eu acho que sim. Experimente e se isso não funcionar, sugiro que você faça uma nova pergunta. Faça referência a este por todos os meios.
roaima 29/10
6

Existem pelo menos 2 utilitários padrão para construir uma árvore de diretórios sombra de uma árvore existente, portanto, não há necessidade de escrever código aqui.

Primeiro há lndir(1)a partir do xutils-devpacote. Ele usa links simbólicos para arquivos. Na página do manual:

NAME
   lndir  -  create a shadow directory of symbolic links to another
             directory tree
SYNOPSIS
   lndir [ -silent ] [ -ignorelinks ] [ -withrevinfo ] fromdir [ todir ]

Uma alternativa talvez melhor é simplesmente usar cpas opções certas, como sugere a resposta aceita. Vou apenas dar mais alguns detalhes úteis:

cp -al /src/dir /dest/dir    # hard-links to leaf-files
cp -as /src/dir /dest/dir    # symlinks to leaf-files

Se você não se preocupa em preservar todos os atributos (propriedades / permissões, horários), substitua a aopção (equivalente a -dr --preserve=all) por r(apenas recursiva):

cp -rl /src/dir /dest/dir    # hard-links to leaf-files
cp -rs /src/dir /dest/dir    # symlinks to leaf-files
arielf
fonte
lndirtambém está disponível como um script shell aqui, caso ele não esteja instalado: opensource.apple.com/source/X11/X11-0.46.4/lndir.sh?txt
Lenar Hoyt
2

Você pode tentar alguns comandos find como este:

mkdir FULL-PATH-TO-COPY
cd SOURCE
find . \( ! -regex '\.' \) -type d -exec mkdir FULL-PATH-TO-COPY/{} \;
find * -type f -exec ln -s `pwd`/{} FULL-PATH-TO-COPY/{} \;
pichogve
fonte
1

Algo assim fará o que você precisa.

#!/bin/bash
#
SOURCE="$1" COPY="$2"
cd "$SOURCE"
find . |
    sed 's!^\./!!' |
    while IFS= read ITEM
    do
        test -d "$ITEM" && { mkdir -p "$COPY/$ITEM"; continue; }
        BASE="${FILE%\/*}"
        ( cd "$COPY/$BASE" && ln -s "$SOURCE/$ITEM" )
    done

Diretórios são criados na árvore COPY de destino. Todo o resto é vinculado novamente ao caminho absoluto na árvore SOURCE. Verifique se SOURCE e COPY estão especificados como caminhos absolutos (começando com /).

Se você tem uma árvore grande para copiar e deseja um relatório de progresso por diretório, pode adicionar um echo "$ITEM" >&2;pouco antes do mkdircomando.

(Eu olhei cpe, cpiomas nenhum deles parece ter uma opção para vincular à fonte com links simbólicos.)

roaima
fonte
1
O comentário "teste da linha 9" pode estar relacionado ao ksh no AIX que deseja que um ponto e vírgula feche a lista entre chaves:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller
@JeffSchaller thanks. Eu não escrevi um kshscript ... mas parece que isso também é necessário bash. Fixação
roaima 04/08
0

Se não houver diretórios vazios em SOURCE que precisem ser copiados

find /full/path/to/SOURCE -type f -exec cp -t COPY --parents -s {} +
mv COPY/full/path/to/SOURCE COPY
rm -r COPY/full
Costas
fonte
1
Desde que você está assumindo o GNU de cpqualquer maneira, por que não cp -as?
Gilles 'SO- stop be evil'
0

Eu começaria quebrando o perl:

#!/usr/bin/perl

use strict;
use warnings;
use File::Find;

my $src_dir = "/full_path/to/dir";
my $tgt_dir = "/path/to/new/location";

sub link_or_mkdir {

    #current file is directory
    if (-d) {
        #extract the path
        my $newpath = $File::Find::dir;
        #change the path so 'old' and 'new' are swapped
        $newpath =~ s,^$src_dir,$tgt_dir,g;
        #print the command to make a new dir (doesn't actually do it)
        print "mkdir -p $newpath\n";
    }
    if (-f) {
        my $new_file = $File::Find::name;
        #change the path so 'old' and 'new' are swapped
        $new_file =~ s,^$src_dir,$tgt_dir,g;
        #print the symlink command
        print "ln -s $File::Find::name $new_file\n";
    }
}

find( \&link_or_mkdir, $tgt_dir );

File::Findé um módulo útil que permite executar uma sub-rotina específica em qualquer arquivo dentro de uma árvore de diretórios. Nesse caso, o sub verifica se é um diretório - e se for, faz um mkdirou um arquivo - nesse caso, faz um link simbólico.

Sobrique
fonte
-1

Parece que você está procurando algo parecido com a ferramenta rsnapshot; ele cria cópias de diretórios arbitrários e usa hardlinks sempre que possível. (Dê uma olhada na página de manual para ver se isso se encaixa.)

Janis
fonte
Não, a pergunta solicita explicitamente links simbólicos e o rsnapshot usa links diretos (pois é uma ferramenta de backup e os arquivos devem ser mantidos mesmo se forem removidos do diretório de origem).
user905686