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.



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

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

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

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).


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

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.


-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.)


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,
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.