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


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.