Come copiare una struttura di cartelle e creare collegamenti simbolici ai file?


21

Ho una cartella SOURCE che contiene diverse cartelle di livello inferiore, ognuna con i propri file.

Voglio copiare questa cartella in una nuova cartella COPIA dove devo copiare la struttura della directory ma mantenere i file come collegamenti simbolici ai file originali in SOURCE e nelle sue sottocartelle.



GNU Stow fa questo.
Kusalananda

Risposte:


27

Ecco la soluzione su Linux e Cygwin non integrati:

cp -as SOURCE/ COPY

Notare che SOURCE deve essere un percorso assoluto e avere una barra finale. Se vuoi dare un percorso relativo, puoi usare

cp -as "$(pwd)/SOURCE/" COPY

Funziona perfettamente, grazie. Solo una nota .. SOURCE deve essere data con il percorso completo (COPY può invece essere data in termini relativi se si desidera)
Antonello

Come farlo funzionare se la directory di origine verrà costantemente aggiornata con nuove cartelle e nuovi file al loro interno? I collegamenti simbolici verranno creati automaticamente nella directory di destinazione nella struttura di cartelle corretta?
SexyBeast,

@AttitudeMonger No, un comando come cp crea i collegamenti una sola volta (come puoi vedere dal risultato). Per aggiornare automaticamente la destinazione, è necessario monitorare la directory di origine per le modifiche.
user905686,

Questo può essere fatto per creare collegamenti relativi?
ctrl-alt-delor,

@richard if SOURCE è un percorso relativo, quindi penso di si. Provalo e se non funziona ti suggerisco di fare una nuova domanda. Fai riferimento a questo con tutti i mezzi.
roaima,

6

Esistono almeno 2 utility standard per creare un albero di directory shadow di un albero esistente, quindi non è necessario scrivere qui il codice.

Prima c'è lndir(1)dal xutils-devpacchetto. Usa collegamenti simbolici ai file. Dalla pagina man:

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

Un'alternativa forse migliore è semplicemente usare cpcon le giuste opzioni come suggerisce la risposta accettata. Darò solo alcuni dettagli più sperabilmente utili:

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

Se non ti interessa conservare tutti gli attributi (proprietà / permessi, orari) sostituisci l' aopzione (equivalente a -dr --preserve=all) con r(solo ricorsivo):

cp -rl /src/dir /dest/dir    # hard-links to leaf-files
cp -rs /src/dir /dest/dir    # symlinks to leaf-files

lndirè disponibile anche come script di shell qui nel caso in cui non sia installato: opensource.apple.com/source/X11/X11-0.46.4/lndir.sh?txt
Lenar Hoyt

2

Puoi provare un paio di comandi find come questo:

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/{} \;

1

Qualcosa del genere farà ciò di cui hai bisogno.

#!/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

Le directory vengono create nella struttura COPY di destinazione. Tutto il resto viene ricollegato al percorso assoluto all'interno dell'albero SOURCE. Assicurarsi che SOURCE e COPY siano specificati come percorsi assoluti (a partire da /).

Se si desidera copiare un albero di grandi dimensioni e si desidera un rapporto sullo stato di avanzamento per directory, è possibile aggiungere echo "$ITEM" >&2;subito prima del mkdircomando.

(Ho guardato cpe cpionessuno dei due sembra avere un'opzione per collegarsi alla fonte con collegamenti simbolici.)


1
Il commento "test linea 9" potrebbe essere correlato a ksh su AIX che voleva un punto e virgola per chiudere l'elenco racchiuso tra parentesi graffe:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller

@JeffSchaller grazie. Non ho scritto una kshsceneggiatura ... ma sembra che sia necessario bashanche per questo. Riparazione
roaima

0

Se non ci sono dir vuoti in SOURCE che devono essere copiati

find /full/path/to/SOURCE -type f -exec cp -t COPY --parents -s {} +
mv COPY/full/path/to/SOURCE COPY
rm -r COPY/full

1
Dato che stai assumendo GNU cpcomunque, perché no cp -as?
Gilles 'SO- smetti di essere malvagio' il

0

Vorrei iniziare rompendo il 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è un modulo utile che consente di eseguire una subroutine specifica su qualsiasi file all'interno di un albero di directory. In questo caso, il sottotitolo verifica se si tratta di una directory e, se lo è, esegue mkdirun file o, nel qual caso esegue un collegamento simbolico.


-1

Sembra che tu stia cercando qualcosa come lo strumento rsnapshot; crea copie di directory arbitrarie e, se possibile, utilizza hardlink. (Dai un'occhiata alla pagina man per vedere se si adatta.)


No, la domanda richiede esplicitamente collegamenti simbolici e rsnapshot utilizza collegamenti fissi (poiché si tratta di uno strumento di backup e i file devono essere conservati anche se rimossi dalla directory di origine).
user905686,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.