回答:
以下は、非組み込みLinuxおよびCygwinでのソリューションです。
cp -as SOURCE/ COPY
SOURCEは絶対パスであり、末尾にスラッシュが必要であることに注意してください。相対パスを指定する場合は、使用できます
cp -as "$(pwd)/SOURCE/" COPY
SOURCE
が相対パスの場合、そう思います。それを試してみて、これがうまくいかない場合は、新しい質問をすることをお勧めします。必ずこれを参照してください。
既存のツリーのシャドウディレクトリツリーを構築するための少なくとも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
このような何かがあなたが必要なことをします。
#!/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
どちらもシンボリックリンクでソースにリンクするためのオプションを持っているようです。)
{ mkdir -p "$COPY/$ITEM"; continue; }
ksh
スクリプトを書きませんでした...しかし、それbash
も必要なようです。修正
コピーする必要がある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
cp
とにかくGNU を想定しているので、なぜcp -as
ですか?
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
か、ファイルであるかを確認します。この場合、シンボリックリンクを実行します。
ツールのようなものを探しているようですrsnapshot
。任意のディレクトリのコピーを作成し、可能な場合はハードリンクを使用します。(manページを見て、適切かどうかを確認してください。)