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


21

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

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



GNU Stow вроде как делает это.
— Кусалананда

Ответы:


27

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

cp -as SOURCE/ COPY

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

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

Работает отлично, спасибо. Просто примечание. ИСТОЧНИК должен быть задан с полным путем (вместо этого КОПИЯ может быть дана в относительном выражении, если хотите)
— Антонелло

Как заставить это работать, если исходный каталог будет постоянно обновляться новыми папками и новыми файлами внутри них? Будут ли символические ссылки на них автоматически создаваться в каталоге назначения в правильной структуре папок?
— 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

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

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но ни один не кажется, есть возможность для подключения к источнику с символическими ссылками.)


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

@JeffSchaller спасибо. Я не писал kshсценарий ... но похоже, что это bashтоже необходимо . Фиксация
— роайма


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или файл - в этом случае она делает символическую ссылку.


-1

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


Нет, вопрос явно требует символических ссылок, а rsnapshot использует жесткие ссылки (так как это инструмент резервного копирования , и файлы следует хранить, даже если они удалены из исходного каталога).
— user905686
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.