4

我被改了目录名。在这个目录中有数千个文件。一些项目使用这个文件,项目上有符号链接。

  1. 如何查找地址中包含文件夹名称的所有符号链接?
  2. 如何在自动模式下将所有这些符号链接更改为另一条路径?

如果 2 只使用删除和创建新的 bash 脚本 - 我会这样做,但您可能知道更简单的方法吗?

4

1 回答 1

16
  1. 这有点复杂,但可以用find,来完成readlink,检查符号链接是否是相对的,并sed去掉路径名(从这个答案..1:1 复制)。(请注意,由于符号链接目标不再存在, 因此最方便的方法(例如)不可用。) 假设您的旧路径是:
    readlink -f
    /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. 现在将...上面的替换为ln -sf(-f以覆盖现有链接)。
    假设您的新路径是/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;' \;
    

请注意,oldpath并且newpath必须是绝对路径。
另请注意,这会将所有相对符号链接转换为绝对符号链接。
保持它们的相对关系是可能的,但需要付出很多努力。

打破它

对于那些关心单线地狱实际上意味着什么的人:

  • find- 一个很酷的可执行文件
  • /- 在哪里搜索,在这种情况下是系统根目录
  • -type l- 匹配符号链接
  • -execdir- 对于每个匹配,在匹配文件的目录中运行以下命令:
    • bash- 好吧,bash
    • -c- 执行以下字符串('删除前导和尾随):
      • p="$(readlink "{}")";- 从最内在的开始:
        • "- 开始一个字符串以确保不会发生扩展
        • {}- 匹配文件名的占位符(的特征-execdir
        • "- 结束字符串
        • readlink ...- 找出符号链接指向的位置
        • p="$(...)"- 并将结果存储在$p
      • if [ "${p:0:1}" != "/" ]; then$p- 如果is的第一个字符/(即符号链接是绝对的),那么...
      • 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}'}"- 将$oldpath部分$p替换为$newpath(实际上删除尽可能多的字符$p$oldpath并添加到它前面$newpath):
          • "- 开始一个字符串
          • '- 结束'-string 参数bash -c
          • "- 附加一个"-string 到它(其中发生变量扩展),包含:
          • $newpath- 的价值$newpath
          • "- 结束"-string 参数bash -c
          • '- 附加一个'-string 到它,包含:
          • ${p:- 的子串p,从:
          • '- 结束争论bash -c
          • ${#oldpath}$oldpath- 附加的长度
          • '- 附加另一个'-string 到它
          • }- 结束子字符串
          • "- 结束字符串
        • "{}"- 链接文件,其路径保持不变
      • fi;- 结尾if
  • \;- 分隔符-execdir
于 2015-06-24T10:25:09.380 回答