如何为多个文件更改符号链接路径?

4

我已经更改了目录名字。

在这个目录中有成千上万的文件。

一些项目使用这些文件,这些项目有符号链接指向它们。

  1. 如何查找所有符号链接,其中地址中包含文件夹名字?
  2. 如何以自动模式更改所有这些符号链接到另一个路径?

如果只用bash脚本删除和创建新的方式-我可以做到,但是也许您知道更简单的方法?

1个回答

17
  1. It's a bit complicated, but it can be done with find, readlink, a check to test whether the symlink is relative or not, and sed to get rid of .. in path names (copied 1:1 from this answer).
    (Note that most convenient methods (such as readlink -f) are not available due to the symlinks targets not existing anymore.)
    Assuming your old path is /var/lib/old/path:

    oldpath='/var/lib/old/path';
    find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ...; fi;' \;
    
  2. Now replace the ... from above with ln -sf (-f to override the existing link).
    Assuming your new path is /usr/local/my/awesome/new/path:

    oldpath='/var/lib/old/path';
    newpath='/usr/local/my/awesome/new/path';
    find / -type l -execdir bash -c 'p="$(readlink "{}")"; if [ "${p:0:1}" != "/" ]; then p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ln -sf "'"$newpath"'${p:'${#oldpath}'}" "{}"; fi;' \;
    
请注意,oldpathnewpath必须是绝对路径。
还要注意,这将把所有相对符号链接转换为绝对符号链接。
保持它们的相对性是可能的,但需要付出大量的努力。

详细解释

对于那些关心这个一行代码到底是什么意思的人:

  • find - 一个很酷的可执行文件
  • / - 要搜索的位置,在这个例子中是系统根目录
  • -type l - 匹配符号链接
  • -execdir - 对于每一个匹配项,在匹配到的文件所在的目录下运行以下命令:
    • bash - 好吧,bash
    • -c - 执行下面的字符串(前后的'被移除):
      • p="$(readlink "{}")"; - 从最内部开始:
        • " - 开始一个字符串以确保没有扩展发生
        • {} - 匹配文件名的占位符(使用-execdir的特性)
        • " - 结束字符串
        • readlink ... - 找出符号链接指向哪里
        • p="$(...)" - 并将结果存储在$p
      • if [ "${p:0:1}" != "/" ]; then - 如果$p的第一个字符不是/(即符号链接是绝对路径),则...
      • p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; - 将路径转换为绝对路径:
        • $(pwd) - 当前目录(因为我们使用了-execdir,所以匹配的文件位于其中)
        • /$p - 将斜杠和符号链接的目标附加到工作目录的路径中
        • echo "$(pwd)/$p" | - 将上述内容传递给下一个命令
        • sed ... - 解析所有..,请参见这里
        • p="$(...)" 并将结果存回$p
      • fi; - 结束if
      • if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; - 如果$p$oldpath开头
        • ${p:0:'${#oldpath}'} - $p的子字符串,从位置0开始,长度为$oldpath
          • ${#oldpath} - 变量$oldpath的长度
          • '...' - 必需,因为我们在一个'-引用字符串中
      • then - 然后...
      • ln -sf - 符号链接并覆盖现有文件,参数为:
        • "'"$newpath"'${p:'${#oldpath}'}" - 用$newpath替换$p$oldpath部分(实际上是从$p中删除与$oldpath长度相同的字符,并将$newpath添加到其中):
          • " - 开始字符串
          • ' - 结束传递

这个故障排除部分是自动工具生成的还是你手动输入的? - dtmland
3
@dtmland 请手动操作。 - Siguza

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