【发布时间】:2015-06-24 07:21:08
【问题描述】:
我被更改了目录名称。 在这个目录中有数千个文件。 一些项目使用这个文件,项目上有符号链接。
- 如何查找地址中包含文件夹名称的所有符号链接?
- 如何在自动模式下将所有这些符号链接更改为另一个路径?
如果 2 只使用删除和创建新的 bash 脚本 - 我会这样做,但您可能知道更简单的方法吗?
【问题讨论】:
我被更改了目录名称。 在这个目录中有数千个文件。 一些项目使用这个文件,项目上有符号链接。
如果 2 只使用删除和创建新的 bash 脚本 - 我会这样做,但您可能知道更简单的方法吗?
【问题讨论】:
这有点复杂,但可以通过find、readlink 来完成,检查符号链接是否是相对的,sed 去掉路径名中的..(复制1:1 来自 this answer)。
(请注意,由于符号链接目标不再存在,大多数方便的方法(例如 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;' \;
现在将上面的 ... 替换为 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 的第一个字符是/(即符号链接是绝对的),那么...p="$(echo "$(pwd)/$p" | sed -e "s|/\./|/|g" -e ":a" -e "s|/[^/]*/\.\./|/|" -e "t a")"; - 将路径转换为绝对路径:
$(pwd) - 当前目录(匹配文件所在的位置,因为我们使用的是-execdir)/$p - 将斜杠和符号链接的目标附加到工作目录的路径echo "$(pwd)/$p" | - 将上述内容传递给下一个命令sed ... - 解决所有 .. 的问题,请参阅 here
p="$(...)" 并将结果存储回$p。fi; - 结束 if
if [ "${p:0:'${#oldpath}'}" == "'"$oldpath"'" ]; - 如果 $p 以 $oldpath 开头
${p:0:'${#oldpath}'} - $p 的子字符串,从位置 0 开始,长度为 $oldpath:
${#oldpath} - 变量的长度 $oldpath
'...' - 必需,因为我们在 '-quoted 字符串中then - 那么...ln -sf - 符号链接并使用参数覆盖现有文件:
"'"$newpath"'${p:'${#oldpath}'}" - 用$newpath 替换$p 的$oldpath 部分(实际上从$p 中删除与$oldpath long 一样多的字符,并在其前面加上$newpath):
" - 开始一个字符串' - 结束 '-string 参数到 bash -c
" - 附加一个 "-string 到它(其中发生变量扩展),包含:$newpath - $newpath 的值
" - 结束 "-string 参数到 bash -c
' - 附加一个'-字符串,包含:${p: - p 的子字符串,起始于:' - 以 bash -c 结束参数
${#oldpath} - 附加 $oldpath 的长度' - 附加另一个 '-string 到它} - 结束子字符串" - 结束字符串"{}" - 链接文件,路径不变fi; - 结束 if
\; - -execdir 的分隔符
【讨论】: