如何递归编辑符号链接的路径?


4

这是从这一个开始的另一个问题 - 如何在OS X中编辑符号链接?

现在我知道如何编辑路径符号链接指向的路径,我正在试图弄清楚如何以递归方式执行任何损坏的符号链接。我是一个PHP家伙,所以这个CLI的东西对我来说有些陌生......

似乎有一些具体要素,即:

  1. 识别损坏的符号链接并检索其位置
  2. 获取符号链接的旧的,现在不正确的目的地
  3. 构造要指向的符号链接的新正确路径
  4. 编辑符号链接

第一个很容易:

find /path/to/search -type l | while read f; do if [ ! -e "$f" ]; then ls -l "$f"; fi; done

这给我一个很好的列表,列出了在提供的目录下找到的所有损坏的符号链接。但我相信我需要将每个位置存储在一个变量(数组?)中才能使用它。

接下来,似乎更改逻辑“then”部分中提供的操作将产生解决方案。

可以使用以下方法检索第2项:

readlink /path/to/broken/symlink

所以我们似乎需要把它推到一个变量中。我不清楚终端如何做到这一点。

3号将是对步骤2中检索到的路径的简单编辑。我需要用新的替换旧的驱动器名称。如此改变:

/Volumes/Old\ Drive/path/to/symlink

/Volumes/New\ Drive/path/to/symlink

还不清楚如何在CLI脚本中执行此操作。似乎需要某种字符串替换。像PHP世界中的str_replace。

最后,步骤4可通过以下方式完成:

ln -f -s /path/to/new/location/of/original /path/to/location/of/broken/symlink/

在我之前的其他问题中有详细说明。

我究竟如何将这些概念串在一起,以实现我一次性修复所有符号链接所需的结果?

Answers:


5

从我的头顶(并没有任何测试):

  1. 使用以下内容创建文本文件

    #!/bin/bash
    
    find "$1" -type l | while read symlink; do
        if [ ! -e "$symlink" ]; then
            old_path=$(readlink "$symlink")
            new_path=${old_path/Old Drive/New Drive}
            ln -f -s "$new_path" "$symlink"
        fi
    done
    
  2. 通过运行使其可执行 chmod +x name-of-file

  3. ./name-of-file /path/to/search

这是 未经测试 所以首先尝试使用示例目录。


添加一些解释

  • old_path=$(readlink "$symlink") 运行命令 $(...) 并将结果分配给 $old_path
  • ${old_path/Old Drive/New Drive} 文本替换 $old_path

谢谢你,但是当我尝试按照指示运行脚本时,我得到了 Run: Command not found
Jonathan van Clute

好吧,你只需要键入行的其余部分(从句点开始)
nohillside

1
我学到了一些新知识 bash 来自这个的语法。所以这是一个赞成!谢谢!
Ian C.

哦!好了,现在跑了。似乎没有做任何事情......符号链接确实有一个新的时间戳,但它们仍然像以前一样被打破。在试图理解你的代码时,我不清楚如何在旧名称上进行字符串替换以将其更改为新代码。
Jonathan van Clute

1
哦,我应该改变这一点。想到它是动态LOL我会调整并回发,如果我还有任何麻烦
Jonathan van Clute

5

在一个 bash shell,设置变量,只需使用 set NAME=bob 要么 set VITAL_SIGNS=none

您还可以通过调用命令的输出来设置变量 bash -builtin功能 read 将输出分配给命名变量。这在管道流中运行良好,如下所示:

ls -l | wc -l | read NUMBER_OF_LINES

或者您可以将输出直接分配给变量,如下所示:

LICENSE_KEY=$(cat ~/software/key.txt | grep KEY | awk '{print $1}')

递归读取变量的一种好方法是循环,如下所示:

for BROKEN_LINK in $(commands to produce a list of files)
do
commands here to sort your links out, noting that the broken links are stored in the variable $BROKEN_LINKS
done

考虑到上述情况,以下内容应该有效:

证明文件夹不存在

StuffeMac:dan stuffe$ ls ~/Desktop/broken_links
ls: /Users/stuffe/Desktop/broken_links: No such file or directory

证明一个新的目标文件夹确实存在

StuffeMac:dan stuffe$ ls ~/Desktop/working_links
StuffeMac:dan stuffe$

创建一些无效且有效的链接

StuffeMac:dan stuffe$ ln -s ~/Desktop/brokenlinks/dan1
StuffeMac:dan stuffe$ ln -s ~/Desktop/brokenlinks/dan2
StuffeMac:dan stuffe$ ln -s ~/Desktop/working_links/dan3
StuffeMac:dan stuffe$ ln -s ~/Desktop/outofscopedeadlinks/dan4
StuffeMac:dan stuffe$ ls -l
total 32
lrwxr-xr-x  1 stuffe  staff  38  8 Dec 10:06 dan1 -> /Users/stuffe/Desktop/brokenlinks/dan1
lrwxr-xr-x  1 stuffe  staff  38  8 Dec 10:06 dan2 -> /Users/stuffe/Desktop/brokenlinks/dan2
lrwxr-xr-x  1 stuffe  staff  40  8 Dec 10:06 dan3 -> /Users/stuffe/Desktop/working_links/dan3
lrwxr-xr-x  1 stuffe  staff  46  8 Dec 10:21 dan4 -> /Users/stuffe/Desktop/outofscopedeadlinks/dan4

将死链接列表抓取到文件中以进行输入

StuffeMac:dan stuffe$ find . -type l | while read f; do if [ ! -e "$f" ]; then ls "$f" >> deadlinks.txt; fi; done
StuffeMac:dan stuffe$ more deadlinks.txt
./dan1
./dan2
./dan4

针对每个死链接运行一个循环

StuffeMac:dan stuffe$ for DEAD_LINK in $(cat deadlinks.txt)
> do
> DESTINATION_IN_SCOPE=$(readlink $DEAD_LINK | grep brokenlinks | wc -l)
> NEW_DESTINATION="~/Desktop/working_links/"
> if [ $DESTINATION_IN_SCOPE = "1" ]
> then
> NEW_LINK=$(echo $DEAD_LINK | colrm 1 2)
> ln -f -s $NEW_DESTINATION$NEW_LINK $DEAD_LINK
> else
> echo "Link $DEAD_LINK not in target folder"
> fi
> done
Link ./dan4 not in target folder
StuffeMac:dan stuffe$

编辑后检查符号链接

StuffeMac:dan stuffe$ ls -l
total 32
lrwxr-xr-x  1 stuffe  staff  28  8 Dec 10:08 dan1 -> ~/Desktop/working_links/dan1
lrwxr-xr-x  1 stuffe  staff  28  8 Dec 10:08 dan2 -> ~/Desktop/working_links/dan2
lrwxr-xr-x  1 stuffe  staff  40  8 Dec 10:06 dan3 -> /Users/stuffe/Desktop/working_links/dan3
lrwxr-xr-x  1 stuffe  staff  46  8 Dec 10:21 dan4 -> /Users/stuffe/Desktop/outofscopedeadlinks/dan4

更现代 bash 从命令中获取输出的方法是使用 $(command) 语法就像 for MYVAR in $(ls | grep somefilter) 而不是使用反引号。它比反叛有一些优势 这个 。我基于此进行了编辑。
Ian C.

1
在SE降价中也不能正确解析;)
stuffe
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.