Как скопировать структуру папок и сделать символические ссылки на файлы?

21

У меня есть папка SOURCE, которая содержит несколько папок подуровня, каждая со своими файлами.

Я хочу скопировать эту папку в новую папку COPY, где мне нужно скопировать структуру каталогов, но сохранить файлы как символические ссылки на исходные файлы в SOURCE и его подпапках.

Антонелло
источник
1
См. Также stackoverflow.com/q/1240636/905686 .
user905686
GNU Stow вроде как делает это.
Кусалананда

Ответы:

27

Вот решение для не встроенных Linux и Cygwin:

cp -as SOURCE/ COPY

Обратите внимание, что SOURCE должен быть абсолютным путем и иметь косую черту. Если вы хотите указать относительный путь, вы можете использовать

cp -as "$(pwd)/SOURCE/" COPY
roaima
источник
Работает отлично, спасибо. Просто примечание. ИСТОЧНИК должен быть задан с полным путем (вместо этого КОПИЯ может быть дана в относительном выражении, если хотите)
Антонелло
Как заставить это работать, если исходный каталог будет постоянно обновляться новыми папками и новыми файлами внутри них? Будут ли символические ссылки на них автоматически создаваться в каталоге назначения в правильной структуре папок?
SexyBeast
@AttitudeMonger Нет, такая команда, как cp, создает ссылки только один раз (как видно из результата). Для автоматического обновления места назначения вам необходимо отслеживать исходный каталог на наличие изменений.
user905686
Можно ли это сделать для создания относительных ссылок?
ctrl-alt-delor
@ Richard Если SOURCE это относительный путь, то я так думаю. Попробуйте, и если это не сработает, я предлагаю вам задать новый вопрос. Ссылка на это непременно.
Ройма
6

Существует как минимум 2 стандартные утилиты для построения теневого дерева каталогов существующего дерева, поэтому здесь не нужно писать код.

Сначала есть lndir(1)из xutils-devпакета. Он использует символические ссылки на файлы. Со страницы руководства:

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

Возможно, лучшая альтернатива состоит в том, чтобы просто использовать cpправильные варианты, как предполагает принятый ответ. Я просто приведу еще несколько, надеюсь, полезных деталей:

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

Если вас не интересует сохранение всех атрибутов (владельцев / разрешений, времени), замените aпараметр (эквивалентный -dr --preserve=all) на r(только рекурсивный):

cp -rl /src/dir /dest/dir    # hard-links to leaf-files
cp -rs /src/dir /dest/dir    # symlinks to leaf-files
arielf
источник
lndirздесь также доступен сценарий оболочки, если он не установлен: opensource.apple.com/source/X11/X11-0.46.4/lndir.sh?txt
Ленар Хойт,
2

Вы можете попробовать пару команд поиска как это:

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
источник
1

Нечто подобное сделает то, что вам нужно.

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

Каталоги создаются в целевом дереве COPY. Все остальное символически связано с абсолютным путем в дереве ИСТОЧНИКОВ. Убедитесь, что SOURCE и COPY указаны как абсолютные пути (начиная с /).

Если у вас есть большое дерево для копирования, и вам нужен отчет о проделанной работе для каждого каталога, вы можете добавить его echo "$ITEM" >&2;непосредственно перед mkdirкомандой.

(Я посмотрел на cpи , cpioно ни один не кажется, есть возможность для подключения к источнику с символическими ссылками.)

roaima
источник
1
Комментарий «Тест строки 9» мог иметь отношение к ksh в AIX, который хотел, чтобы точка с запятой закрывала список в скобках:{ mkdir -p "$COPY/$ITEM"; continue; }
Джефф Шаллер
@JeffSchaller спасибо. Я не писал kshсценарий ... но похоже, что это bashтоже необходимо . Фиксация
роайма
0

Если в SOURCE нет пустых папок, которые нужно скопировать

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
Так как в cpлюбом случае вы принимаете GNU , почему бы и нет cp -as?
Жиль "ТАК - перестань быть злым"
0

Я бы начал с разрыва 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это полезный модуль, который позволяет запускать определенную подпрограмму для любого файла в дереве каталогов. В этом случае подпрограмма проверяет, является ли она каталогом - и если это так, делает mkdirили файл - в этом случае она делает символическую ссылку.

Sobrique
источник
-1

Кажется, вы ищете что-то вроде инструмента rsnapshot; он создает копии произвольных каталогов и использует жесткие ссылки, где это возможно. (Посмотрите справочную страницу, чтобы понять, подходит ли она.)

Janis
источник
Нет, вопрос явно требует символических ссылок, а rsnapshot использует жесткие ссылки (так как это инструмент резервного копирования , и файлы следует хранить, даже если они удалены из исходного каталога).
user905686