Як скопіювати структуру папки та зробити символічні посилання на файли?


21

У мене є папка ДЖЕРЕЛО, яка містить декілька папок нижнього рівня, кожна з яких має власні файли.

Я хочу скопіювати цю папку в нову папку COPY, де мені потрібно скопіювати структуру каталогів, але зберегти файли як символічні посилання на вихідні файли в SOURCE та його підпапках.



GNU Stow свого роду це робить.
Kusalananda

Відповіді:


27

Ось рішення щодо невбудованих Linux та Cygwin:

cp -as SOURCE/ COPY

Зауважте, що ДЖЕРЕЛО повинно бути абсолютним шляхом і мати кінцеву косу рису. Якщо ви хочете дати відносний шлях, ви можете використовувати

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

Працює ідеально, дякую. Лише зауваження .. ДЖЕРЕЛО потрібно надати повний шлях (натомість КОПІЮ можна надати відносно, якщо хочете)
Antonello

Як змусити його працювати, якщо вихідний каталог буде постійно оновлюватися новими папками та новими файлами всередині них? Чи будуть автоматично створені символьні посилання в каталозі призначення у правильній структурі папок?
SexyBeast

@AttitudeMonger Ні, така команда, як cp, просто створює посилання один раз (як видно з результату). Щоб автоматично оновлювати призначення, вам доведеться стежити за джерелом каталогу за змінами.
користувач905686

Чи можна це зробити для створення відносних зв’язків?
ctrl-alt-delor

@richard якщо SOURCE це відносний шлях, то я так думаю. Спробуйте, і якщо це не допоможе, я пропоную вам запитати нове запитання. Посилайтеся на це будь-якими способами.
roaima

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
Lenar Hoyt

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. Все інше пов'язане назад до абсолютного шляху в межах ДЖЕРЕЛА. Переконайтесь, що і ДЖЕРЕЛО, і КОПІЯ вказані як абсолютні шляхи (починаючи з /).

Якщо у вас є велике дерево для копіювання, і ви хочете звіт про хід виконання каталогу, ви можете додати його echo "$ITEM" >&2;безпосередньо перед mkdirкомандою.

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


1
Коментар "тест 9 рядка", можливо, стосувався ksh на AIX, який хоче, щоб крапкою з комою було закрито список, що вкладається в дужки:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller

@JeffSchaller дякую. Я не писав kshсценарій ... але, схоже, це bashтеж потрібно. Фіксація
roaima


0

Я б почав, вириваючи перл:

#!/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 використовує жорсткі посилання (оскільки це резервний інструмент, і файли слід зберігати, навіть якщо вони видалені з вихідного каталогу).
користувач905686
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.