Jak skopiować strukturę folderów i tworzyć dowiązania symboliczne do plików?

21

Mam folder SOURCE, który zawiera kilka folderów podrzędnych, każdy z własnymi plikami.

Chcę skopiować ten folder do nowego folderu KOPIUJ, w którym muszę skopiować strukturę katalogów, ale zachowaj pliki jako symboliczne łącza do oryginalnych plików w ŹRÓDŁU i jego podfolderach.

Antonello
źródło
1
Zobacz także stackoverflow.com/q/1240636/905686 .
user905686,
GNU Stow trochę to robi.
Kusalananda

Odpowiedzi:

27

Oto rozwiązanie dotyczące niewbudowanego systemu Linux i Cygwin:

cp -as SOURCE/ COPY

Zauważ, że ŹRÓDŁO musi być ścieżką bezwzględną i ukośnikiem. Jeśli chcesz podać ścieżkę względną, możesz użyć

cp -as "$(pwd)/SOURCE/" COPY
roaima
źródło
Działa idealnie, dziękuję. Tylko uwaga. ŹRÓDŁO musi być podane pełną ścieżką (KOPIA może być podana względnie, jeśli ktoś chce)
Antonello
Jak to działa, jeśli katalog źródłowy będzie stale aktualizowany o nowe foldery i nowe pliki w nich zawarte? Czy dowiązania symboliczne do nich będą automatycznie tworzone w katalogu docelowym w prawidłowej strukturze folderów?
SexyBeast,
@AttitudeMonger Nie, takie polecenie jak cp tylko raz tworzy linki (jak widać z wyniku). Aby automatycznie zaktualizować miejsce docelowe, musisz monitorować katalog źródłowy pod kątem zmian.
user905686,
Czy można to zrobić, aby utworzyć linki względne?
ctrl-alt-delor
@richard, jeśli SOURCE jest ścieżką względną, to tak myślę. Spróbuj, a jeśli to nie zadziała, sugeruję, aby zadać nowe pytanie. Odwołaj się do niego za wszelką cenę.
roaima
6

Istnieją co najmniej 2 standardowe narzędzia do budowy drzewa katalogów cień istniejącego drzewa, więc nie trzeba tutaj pisać kodu.

Najpierw jest lndir(1)z xutils-devpaczki. Wykorzystuje dowiązania symboliczne do plików. Ze strony podręcznika:

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

Być może lepszą alternatywą jest po prostu użycie cpwłaściwych opcji, jak sugeruje zaakceptowana odpowiedź. Podam tylko kilka przydatnych informacji:

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

Jeśli nie zależy Ci na zachowaniu wszystkich atrybutów (własności / uprawnień, czasów), zamień aopcję (równoważną -dr --preserve=all) na r(tylko rekurencyjne):

cp -rl /src/dir /dest/dir    # hard-links to leaf-files
cp -rs /src/dir /dest/dir    # symlinks to leaf-files
arielf
źródło
lndirjest również dostępny tutaj jako skrypt powłoki na wypadek, gdyby nie został zainstalowany: opensource.apple.com/source/X11/X11-0.46.4/lndir.sh?txt
Lenar Hoyt
2

Możesz wypróbować kilka takich poleceń wyszukiwania:

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
źródło
1

Coś takiego zrobi to, czego potrzebujesz.

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

Katalogi są tworzone w docelowym drzewie KOPIOWANIA. Cała reszta jest połączona symbolicznie z powrotem do absolutnej ścieżki w drzewie SOURCE. Upewnij się, że zarówno ŹRÓDŁO, jak i KOPIA są określone jako ścieżki bezwzględne (zaczynając od /).

Jeśli masz duże drzewo do skopiowania i potrzebujesz raportu postępu dla poszczególnych katalogów, możesz dodać go echo "$ITEM" >&2;tuż przed mkdirpoleceniem.

(I spojrzał cpi cpioale nie wydaje się mieć opcję linkami do źródła z linków symbolicznych).

roaima
źródło
1
Komentarz do „testu 9 linii” mógł mieć związek z tym, że ksh w systemie AIX chciał, aby średnik zamykał listę zamkniętą nawiasami klamrowymi:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller
@JeffSchaller dzięki. Nie napisałem kshskryptu ... ale wygląda na to, że jest to również konieczne bash. Naprawianie
roaima,
0

Jeśli w ŹRÓDŁO nie ma pustych katalogów, które należy skopiować

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
źródło
1
Skoro i tak zakładasz GNU cp, dlaczego nie cp -as?
Gilles „SO- przestań być zły”
0

Zacznę od wyrwania perla:

#!/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::Findjest przydatnym modułem, który pozwala uruchomić określoną podprogram na dowolnym pliku w drzewie katalogów. W takim przypadku podrzędny sprawdza, czy jest to katalog - a jeśli tak, robi plik mkdirlub plik - w takim przypadku robi dowiązanie symboliczne.

Sobrique
źródło
-1

Wygląda na to, że szukasz czegoś takiego jak narzędzie rsnapshot; tworzy kopie dowolnych katalogów i w miarę możliwości używa twardych łączy. (Zajrzyj na stronę podręcznika, aby sprawdzić, czy to pasuje.)

Janis
źródło
Nie, pytanie wyraźnie pyta o dowiązania symboliczne, a rsnapshot używa dowiązań twardych (ponieważ jest to narzędzie do tworzenia kopii zapasowych , a pliki powinny być przechowywane, nawet jeśli zostaną usunięte z katalogu źródłowego).
user905686,