如何复制文件夹结构并建立文件的符号链接?


21

我有一个文件夹SOURCE,其中包含几个子级别的文件夹,每个文件夹都有其自己的文件。

我想将此文件夹复制到新文件夹COPY中,在该文件夹中,我需要复制目录结构,但是将这些文件作为符号链接保留到SOURCE及其子文件夹中的原始文件。



GNU Stow还可以做到这一点。
库萨兰达

Answers:


27

这是非嵌入式Linux和Cygwin上的解决方案:

cp -as SOURCE/ COPY

请注意,SOURCE必须是绝对路径,并带有斜杠。如果要提供相对路径,可以使用

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

完美的作品,谢谢。请注意。.必须以完整的路径给出源(如果愿意,可以相对地给出COPY)
Antonello

如果源目录中的新文件夹和新文件不断更新,如何使它起作用?是否会在目标目录中以正确的文件夹结构自动创建指向它们的符号链接?
SexyBeast

@AttitudeMonger不,像cp这样的命令仅创建一次链接(从结果中可以看到)。要自动更新目标,您必须监视源目录中的更改。
user905686 '16

可以这样做来创建相对链接吗?
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如果尚未安装,也可以在此处作为shell脚本使用: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树中创建目录。其他所有内容都符号链接回SOURCE树中的绝对路径。确保将SOURCE和COPY都指定为绝对路径(以开头/)。

如果您要复制一棵大树,并且需要每个目录的进度报告,则可以echo "$ITEM" >&2;mkdir命令之前添加。

(我看着cpcpio但也似乎有链接到符号链接的源的选项。)


1
“第9行测试”注释可能与AIX上的ksh有关,该命令希望使用分号关闭大括号内的列表:{ mkdir -p "$COPY/$ITEM"; continue; }
Jeff Schaller

@JeffSchaller谢谢。我没有写ksh脚本...但是看起来这也是必要的bash。修复
roaima

0

如果源中没有空的目录,需要复制

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
既然您仍然假设使用GNU cp,为什么不cp -as呢?
吉尔斯(Gilles)'所以

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 '16
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.