符号链接-复制一个目录层次结构

30

在Linux中,最简单的方法是如何“复制”目录结构以创建一个新的目录层次结构,而所有“文件”只是符号链接,指向源目录上的实际文件?

cp -s不支持递归操作。


1
请参见http://unix.stackexchange.com/q/196537/10047。 - user905686
7个回答

39

我刚在Linux系统上进行了一个快速测试,cp -sR /orig /dest 正是你所描述的:创建一个包含非目录符号链接指向原始文件的目录层次结构。


4
它只能在第一个目录层级上运行。对于子目录中的每个文件,我会得到“xyz-file:只能在当前目录中创建相对符号链接”的提示。(在Ubuntu 8.10上,cp版本为6.10) - Max Spring
37
你收到“xyz-file: can make relative symbolic links only in current directory”错误的原因是,对于源目录,你指定了一个相对路径。如果你为源指定绝对路径,例如:“cp -sR /root/absolute/path/name dest”,它将按照你所期望的方式工作。请注意,只能在当前目录中创建相对符号链接。 - PonyEars
6
如果您需要/希望将所有符号链接改为相对路径,您可以使用symlinks命令执行以下操作:cp -sR /orig /dest && symlinks -rc /dest - Nathan S. Watson-Haigh
4
并非所有系统都适用。在Mac/PowerPC上,我得到了cp: illegal option -- s的错误提示,因此如果您需要编写一个可移植的脚本,您需要采用另一种方法。 - user1985657
@avp 这个问题明确指出是在Linux上,并要求“最简单”的解决方案。Drew Stephens的答案适用于其他许多Unix环境,但在典型的Linux系统上似乎不是最简单的解决方案。 - freiheit
显示剩余7条评论

19
cp -as /root/absolute/path/name dest_dir

会做你想要的事。请注意,源名称必须是绝对路径,不能是相对路径。否则,您将收到此错误:“xyz-file:仅在当前目录中创建相对符号链接。”

此外,请注意复制的内容:如果dest_dir已经存在,则需要执行类似以下操作:

cp -as /root/absolute/path/name/* dest_dir/
cp -as /root/absolute/path/name/.* dest_dir/

13

从原目录和新目录上方开始,我认为下面这对find(1)命令将满足您的需求:

find original -type d -exec mkdir new/{} \;
find original -type f -exec ln -s {} new/{} \;

第一个实例通过在原始树中仅查找目录并在新树中重新创建它们来设置目录结构。第二个实例将符号链接创建到新树中的原始文件。


1
这对我非常有效(如上所述,cp -as或-Rs在Mac OS X上不起作用)。为了获得相对路径作为mkdir和ln -s的参数,可能最好使用(cd origParentDir; find origDir ..; find origDir ..)。使用括号来启动()子shell,因为在子shell中运行cd仅会临时设置CWD;当子shell退出时,CWD将被恢复。例如,如果您要将“/src/binutils-2.24”克隆到${HOME}/source,则不希望创建“src”文件夹。 - user1985657
奇怪的是 ln 没有递归选项... 就像 ln -s -R orig/dir dest/dir - jiggunjer

7

2
我和原问题提问者遇到了完全相同的问题,在开始编写一个 Shell 脚本后,找到了这个答案并发现 lndir 已经被安装。它完全符合我的需求。 - shmuelp

1

如果你想动手尝试一下,这里有一个技巧可以自动创建目标文件夹、子文件夹并递归地建立所有符号链接。

在你想要建立符号链接和子文件夹的文件夹中:

  1. 创建一个名为 shell.sh 的文件:

    nano shell.sh

  2. 复制并粘贴以下代码:

#!/bin/bash

export DESTINATION=/your/destination/folder/
export TARGET=/your/target/folder/

find . -type d -print0 | xargs -0 bash -c 'for DIR in "$@"; 
do
  echo "${DESTINATION}${DIR}"
  mkdir -p "${DESTINATION}${DIR}"        
  done' -


find . -type f -print0 |  xargs -0 bash -c 'for file in "$@"; 
do
  ln -s  "${TARGET}${file}"  "${DESTINATION}${file}"
   done' -
  1. 保存文件 ctrl+O
  2. 关闭文件 ctrl+X
  3. 使脚本可执行 chmod 777 shell.sh

  4. 运行脚本 ./shell.sh

祝你愉快的黑客之旅!


1

我在谷歌上搜索了一下,发现有一个命令叫做lns,可以从这里获取。


为什么你会推荐使用第三方工具,如果cp命令加上一些(2)选项就可以解决问题。这对我来说似乎是一个安全风险。 - Nikodemus RIP
因为我在八年前回答这个问题时不知道-s选项。如果您认为答案好/坏,请随意点赞/踩。 - JesperE

0

我知道这个问题是关于shell的,但是由于您可以从shell调用perl,因此我编写了一个类似于这个非常类似的工具,并在几年前perlmonks发布了它。在我的情况下,我通常希望目录保持链接状态,直到我决定否则为止。自动和递归地完成这个任务将是一个相当微不足道的变化。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接