フォルダ構造をコピーして、ファイルへのシンボリックリンクを作成する方法


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

完璧に動作します、ありがとう。ただ、ノート.. SOURCEは、(1希望する場合COPYではなく、相対的な用語で与えられる)フルパスで指定する必要があり
アントネッロ

ソースディレクトリが新しいフォルダーとその中の新しいファイルで絶えず更新される場合、どのように機能させるのですか?それらへのシンボリックリンクは、正しいフォルダー構造で宛先ディレクトリに自動的に作成されますか?
SexyBeast

@AttitudeMongerいいえ、cpなどのコマンドは、リンクを1回だけ作成します(結果からわかるように)。宛先を自動的に更新するには、ソースディレクトリの変更を監視する必要があります。
user905686

相対リンクを作成するためにこれを行うことはできますか?
ctrl-alt-delor

@richard if SOURCE が相対パスの場合、そう思います。それを試してみて、これがうまくいかない場合は、新しい質問をすることをお勧めします。必ずこれを参照してください。
ロアイマ

6

既存のツリーのシャドウディレクトリツリーを構築するための少なくとも2つの標準ユーティリティがあるため、ここにコードを記述する必要はありません。

最初にパッケージlndir(1)からのものがありxutils-devます。ファイルへのシンボリックリンクを使用します。manページから:

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ツリー内の絶対パスにシンボリックリンクされます。SOURCEとCOPYの両方が(で始まる/)絶対パスとして指定されていることを確認してください。

コピーする大きなツリーがあり、ディレクトリごとの進捗レポートが必要な場合はecho "$ITEM" >&2;mkdirコマンドの直前に追加できます。

(私は見ていないcpし、cpioどちらもシンボリックリンクでソースにリンクするためのオプションを持っているようです。)


1
:「9行目のテスト」のコメントは括弧で囲まれたリスト閉じるために、セミコロンを望むAIX上のkshに関連している可能性{ 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ですか?
ジル 'SO-悪であるのをやめる'

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。任意のディレクトリのコピーを作成し、可能な場合はハードリンクを使用します。(manページを見て、適切かどうかを確認してください。)


いいえ、質問は明示的にシンボリックリンクを要求し、rsnapshotはハードリンクを使用します(バックアップツールであり、ファイルはソースディレクトリから削除されても保持される必要があるため)。
user905686
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.