用原始代码替换所有符号链接

Ken*_*awa 28 bash symlink

我有以下目录结构

/symdir
  sym1 -> ../dir1
  sym2 -> ../dir2
  hello.txt
Run Code Online (Sandbox Code Playgroud)

然后

/dir1
  some
  files
  here
/dir2
  more
  files
Run Code Online (Sandbox Code Playgroud)

我想将symdir(sym1,sym2)中的符号链接替换为原始符号.即

some_awesome_bash_func symdir symdir_output
Run Code Online (Sandbox Code Playgroud)

会创造

/symdir_output
  /dir1
    some
    files
    here
  /dir2
    more
    files
  hello.txt
Run Code Online (Sandbox Code Playgroud)

我怎么做到这一点?

Jul*_*ard 66

我个人的伎俩:

sed -i '' **/*
Run Code Online (Sandbox Code Playgroud)

请注意,我正在使用**哪个使用bash globstar选项,您可能必须事先启用它:

shopt -s globstar
Run Code Online (Sandbox Code Playgroud)

  • 这是我今天读到的最可怕的事情. (70认同)
  • 它有什么作用 ?怎么可能`sed`可能复制文件? (4认同)
  • 很有意思.我对这项工作有点惊讶.(cc @LeVieuxGildas - 它**工作) (3认同)
  • @ZacharyVance 如果您有更好/更清洁/任何解决方案,请随时发布;-) (2认同)
  • ELI5:`** / *`将目录中的所有文件扩展到命令`sed -i'。`在文件内容中不做任何更改,这利用了sed使用临时文件并替换原始文件这一事实,看起来很有效也适用于目录。来源:https://www.reddit.com/r/programming/comments/9ktb2o/using_sed_to_replace_symlinks_with_a_copy_of_the/ (2认同)

Jon*_*end 24

您可以使用rsync轻松完成此操作:

rsync symdir/ symdir_output/ -a --copy-links -v
Run Code Online (Sandbox Code Playgroud)

(-a表示基本保留有关文件的每个细节, - copy-links覆盖-a将符号链接转换为真实文件/目录,-v表示详细)

编辑:

对不起,我的解决方案并没有完全符合您的要求.它将保留符号链接的名称,而不是使用目标名称.symdir_output将有sym1和sym2而不是dir1和dir2(虽然sym1和sym2将是dir1和dir2的真实副本).希望它仍然适合你.


Pin*_*oyd 13

一个相关的答案,这个解决方案将文件保存在原始位置,并创建一个副本来代替符号链接

#/bin/bash

for f in $(find . -maxdepth 1 -type l)
do
    cp --remove-destination $(readlink -e $f) $f
done
Run Code Online (Sandbox Code Playgroud)

  • 该解决方案(用“mv”替换“cp”并删除“--remove-destination”)是唯一完全按照我的预期工作的解决方案。它用原始文件替换符号链接并删除旧位置。 (2认同)
  • 你会想要双引号这些参数扩展;如果目录不是`./`,也使用`readlink -f`:`for f in $(find . -maxdepth 1 -type l) do cp --remove-destination "$(readlink -f "$ f")" "$f" 完成`。请注意,循环参数的拆分是可疑的...... (2认同)

Dan*_*ley 10

可能不是最好的方式,但它有效:

#!/usr/bin/bash

for link in $(find /symdir -type l)
do
  loc="$(dirname "$link")"
  dir="$(readlink "$link")"
  mv "$dir" "$loc"
  rm "$link"
done
Run Code Online (Sandbox Code Playgroud)

  • `readlink"$ link"`给出下一个链接...`readlink -e"$ link"`给出一系列链接的最终目标. (4认同)
  • 请注意,您的文件名不能包含空格; 否则`mv`命令会中断 (3认同)

Mik*_*rge 6

tl; dr:更通用,更可靠的答案:

find -type l -exec sh -c 'PREV=$(realpath -- "$1") && rm -- "$1" && cp -ar -- "$PREV" "$1"' resolver {} \;
Run Code Online (Sandbox Code Playgroud)

"rsync-to-other-destination"方法非常优越,通常可以带来更好的设计.

@PinkFloyd的答案与不寻常的文件名,"埋藏"符号链接或符号链接目录不太一致.我来到这里是因为我想解析目录符号链接,所以我希望其他人也可以出于这个原因找到这个问题.另外,我的cp(GNU coreutils 8.25)版本没有正确处理--remove-destination@ PinkFloyd使用目录的答案.所以这个答案使用手册rm.

另请注意:

  • 缺席-rf.这是因为符号链接不是目录,不应该需要-r.除非你有限制权限的符号链接(你为什么要这么做?!),你也不需要-f.
  • realpath在这种情况下完全没问题,因为它允许我们在当前环境中找出当前系统中的实际位置,而其他任何事情都不重要.此路径不会写入磁盘,因此这不是错误.
  • resolver字符串是sh.见man sh.
  • 在某些符号链接被调用--version或类似的情况下,到处都需要双破折号.
  • 由于find("父目录在其内容之前的某个地方列出")的预订保证,这将首先替换父目录,然后替换符号链接目录中的任何符号链接.所以它可以与"堆叠"符号链接完美搭配.