简体   繁体   English

如何更改许多文件的符号链接路径?

[英]How change symlink path for many files?

I was changed directory name.我是改了目录名。 In this directory thousands of files.在这个目录中有数千个文件。 Some projects use this files, projects have got symlinks on it.一些项目使用这个文件,项目有符号链接。

  1. How to find all symlinks, which have got folder name in their address?如何找到所有在其地址中有文件夹名称的符号链接?
  2. how to change all this symlinks to another path in automatic mode?如何在自动模式下将所有这些符号链接更改为另一个路径?

if 2 only bash scripting with deleting and creating new - i will do it, but may be you know more easy way?如果 2 只有删除和创建新的 bash 脚本 - 我会这样做,但你可能知道更简单的方法吗?

  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 ).这有点复杂,但可以通过findreadlink 、检查符号链接是否是相对的,以及sed来摆脱路径名中的.. (从这个答案中以1:1 复制)来完成。
    (Note that most convenient methods (such as readlink -f ) are not available due to the symlinks targets not existing anymore.) (请注意,由于符号链接目标不再存在,最方便的方法(例如readlink -f )不可用。)
    Assuming your old path is /var/lib/old/path :假设您的旧路径是/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 "ta")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ...; fi;' \\;
  2. Now replace the ... from above with ln -sf ( -f to override the existing link).现在用ln -sf-f覆盖现有链接)替换上面的...
    Assuming your new path is /usr/local/my/awesome/new/path :假设您的新路径是/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 "ta")"; fi; if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; then ln -sf "'"$newpath"'${p:'${#oldpath}'}" "{}"; fi;' \\;

Note that oldpath and newpath have to be absolute paths.请注意, oldpathnewpath必须是绝对路径。
Also note that this will convert all relative symlinks to absolute ones.另请注意,这会将所有相对符号链接转换为绝对符号链接。
It would be possible to keep them relative, but only with a lot of effort.将它们保持相对是可能的,但需要付出很多努力。

Breaking it down打破它

For those of you who care what that one-line-inferno actually means:对于那些关心单行地狱实际上意味着什么的人:

  • find - a cool executable find - 一个很酷的可执行文件
  • / - where to search, in this case the system root / - 搜索位置,在本例中为系统根目录
  • -type l - match symbolic links -type l - 匹配符号链接
  • -execdir - for every match run the following command in the directory of the matched file: -execdir - 对于每个匹配项,在匹配文件的目录中运行以下命令:
    • bash - well, bash bash - 好吧,bash
    • -c - execute the following string (leading and trailing ' removed): -c - 执行以下字符串(前导和尾随'已删除):
      • p="$(readlink "{}")"; - starting with the most inner: - 从最内在的开始:
        • " - start a string to make sure no expansion happens " - 开始一个字符串以确保不会发生扩展
        • {} - placeholder for the matched file's name (feature of -execdir ) {} - 匹配文件名的占位符( -execdir功能)
        • " - end the string " - 结束字符串
        • readlink ... - find out where the symlink points to readlink ... - 找出符号链接指向的位置
        • p="$(...)" - and store the result in $p p="$(...)" - 并将结果存储在$p
      • if [ "${p:0:1}" != "/" ]; then if [ "${p:0:1}" != "/" ]; then - if the first character of $p is / (ie the symlink is absolute), then... if [ "${p:0:1}" != "/" ]; then - 如果$p的第一个字符是/ (即符号链接是绝对的),那么...
      • p="$(echo "$(pwd)/$p" | sed -e "s|/\\./|/|g" -e ":a" -e "s|/[^/]*/\\.\\./|/|" -e "ta")"; - convert the path to an absolute one: - 将路径转换为绝对路径:
        • $(pwd) - the current directory (where the matched file lies, because we're using -execdir ) $(pwd) - 当前目录(匹配文件所在的目录,因为我们使用的是-execdir
        • /$p - append a slash and the target of the symlink to the path of the working directory /$p - 将斜杠和符号链接的目标附加到工作目录的路径
        • echo "$(pwd)/$p" | - pipe the above to the next command - 将上述内容通过管道传递到下一个命令
        • sed ... - resolve all .. 's, see here sed ... - 解决所有..的问题,请参见此处
        • p="$(...)" and store the result back into $p . p="$(...)"并将结果存储回$p
      • fi; - end if - 结束if
      • if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; - if $p starts with $oldpath - 如果$p$oldpath
        • ${p:0:'${#oldpath}'} - substring of $p , starting at position 0 , with length of $oldpath : ${p:0:'${#oldpath}'} - $p子字符串,从位置0开始,长度为$oldpath
          • ${#oldpath} - length of variable $oldpath ${#oldpath} - 变量$oldpath长度
          • '...' - required because we're inside a ' -quoted string '...' - 必需,因为我们在一个'引用的字符串中
      • then - then... then ——然后……
      • ln -sf - link symbolically and override existing file, with arguments: ln -sf - 符号链接并覆盖现有文件,带参数:
        • "'"$newpath"'${p:'${#oldpath}'}" - replace the $oldpath part of $p with $newpath (actually remove as many characters from $p as $oldpath long is, and prepend $newpath to it): "'"$newpath"'${p:'${#oldpath}'}" - 用$newpath替换$p$oldpath部分(实际上从$p删除与$oldpath long 一样多的字符,并在前面加上$newpath ):
          • " - start a string " - 开始一个字符串
          • ' - end the ' -string argument to bash -c ' - 结束' -string 参数到bash -c
          • " - append a " -string to it (in which variable expansion happens), containing: " - 附加一个" -string 到它(其中发生变量扩展),包含:
          • $newpath - the value of $newpath $newpath -价值$newpath
          • " - end the " -string argument to bash -c " - 结束" -string 参数给bash -c
          • ' - append a ' -string to it, containing: ' - 附加一个' -string 到它,包含:
          • ${p: - a substring of p , starting at: ${p: -的一个子p ,起始于:
          • ' - end the argument to bash -c ' - 结束参数bash -c
          • ${#oldpath} - append the length of $oldpath to it ${#oldpath} - 附加$oldpath的长度
          • ' - append another ' -string to it ' - 附加另一个' -string
          • } - end substring } - 结束子串
          • " - end string " - 结束字符串
        • "{}" - the link file, whose path stays the same "{}" - 链接文件,其路径保持不变
      • fi; - end if - 结束if
  • \\; - delimiter for -execdir - -execdir分隔符

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM