递归符号链接目录树

3
我正在尝试从一个目录递归地创建符号链接到另一个目录:
find data/* -type d -exec ln -s {} current/{} \;

再加上一点:我需要从前缀中去掉data/

在运行OS X服务器(10.8,Mountain Lion)时,不支持所有标准的GNU命令,例如cp -rs

我所说的递归是指:

data是Laravel版本之间持久目录的列表:

data/
    \ storage/
        - framework/
            - session/
        - app/
        \ logs/

他们需要映射到:

current/
    \ storage/
        - framework
            - session/
        - app/
        - logs/
      # Also in storage, but we do NOT want to persist
        - debugbar/
        - framework/
            - cache/
            - views/

我们的data目录将在应用程序启动之间保留持久性存储,当我们更新网站时,会保留先前版本的网站以进行回滚(current恰好是最新发布的软链接)。
注意:除了Laravel之外,我们还有其他网站。 data将成为我们的标准,并根据网站对持久性的要求匹配目录重组。它不总是data/storage

你能解释一下“递归”是什么意思吗?一旦你从 current/foo 创建了到 data/foo 的链接(例如),所有它的子目录都可以通过该链接访问... 你不需要做任何额外的事情。 - user149341
@duskwuff - 已经明确表示了,不要递归。你可以简单地使用 find data -maxdepth 1 -type d -exec ln -s ../{} current \; - alvits
@duskwuff: data/foo/bar => current/foo/bardata/foo/bartwo/play => current/foo/bartwo/play - guice
3个回答

5

您不需要进行任何递归操作。一旦链接到了一个目录,其下的所有文件和子目录都可以通过该链接访问。

您只需要链接到顶层目录中的目录即可...

cd current
ln -s ../data/*/ .

或者,根据您的要求,将“current”作为指向“data”的链接甚至可能已经足够了。

错误。你最终会得到指向无处的链接的“current”。尝试使用“cd current; ln -s ../data/*/ .”。 - alvits
@alvits 谢谢,已经修复了。(或者直接使用绝对路径到“current”) - user149341
抱歉,我忘了提到 data 目录不是完整的目录集合,只是要共享的子集。我会更新帖子。 - guice
@duskwuff 哦,我试了一下。 没有成功,因为current是指向release / {revnum} /的符号链接 - 由于符号链接的路径解析,导致找不到../data - guice
对于我来说,需要运行两个命令:1. 用于创建文件符号链接(ln -s ../data/*.),和2. 用于创建子目录符号链接(ln -s ../data// .)。 - Pranaysharma

4

GNU stow. https://www.gnu.org/software/stow/

尝试以下操作:

# cd to dir above ./data
mkdir datalinks
stow -d datalinks data

Stow会智能地处理源目录中的现有文件。如果目录不存在,它将创建符号链接,但如果存在,则将创建内容的符号链接。

需要一些时间才能理解,但一旦理解,它就打开了一种关于文件/符号链接管理的新思路。 想象一个稀疏树,只有新文件是实际文件,其他所有内容都是指向之前内容的符号链接 - 这就是苹果的Time Machine。如果你曾经在shell中浏览过Time Machine备份,你会发现它与rsnapshot备份完全相同。 所有这些都基于稀疏树符号链接的填充,而stow则是瑞士军刀。


1
这种方法比被接受的答案更安全,因为问题没有明确说明 @guice 尝试创建的子目录结构(任何部分)是否已经存在;我相信一些建议的答案会意外地用新的结构覆盖掉现有结构的某些部分。 - Jason Hemann
1
同意,stow 是一个不为人知的英雄。它没有得到应有的赞扬。 - Bruce Edge

3

我将回答如何递归地从一个目录链接到另一个目录中的所有文件。

我需要这个功能,但在macOS上找不到好的解决方案。

以下是最佳可用解决方案:

cp -Rs <src_dir> <dest_dir>

否则,我所做的是:
#! /usr/bin/env bash

symlink_recursive_copy() {
    local src_dir=$1 ; shift
    local target_dir=$1
    local basename
    local cdir
    local full_path_cdir
    local full_path_target_dir
    local opwd=$PWD

    if [ -e "$target_dir" ]
    then
        >&2 echo "$target_dir already exists"
        return 1
    fi

    target_dir="$opwd/${target_dir##*/}"

    cd "$src_dir"

    while IFS= read -r -d '' file
    do
        basename="${file##*/}"
        cdir="${file%/*}"
        cd "$cdir" ; full_path_cdir=$PWD ; cd "$OLDPWD"
        mkdir -p "$target_dir/$cdir"
        ln -s "$full_path_cdir/$basename" "$target_dir/$cdir/$basename"
    done < <( find . -type f -print0 )

    cd "$opwd"
}

symlink_recursive_copy "$@"

上述方法适用于任何包含换行符、空格、引号、尾部换行符等的文件。


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