Shell – automate the process of fixing all broken links

shell-scriptsymlink

There are lots of broken links in my system. I wrote a script to relink all broken links. But, after the scripts runs, find would again show me that the links still exists.

This is my code:

find /home/saman -lname '/home/saman/*' -exec \
   sh -c 'ln -snf "/home$(readlink "$0")" "$0"' {} \;

After running the command above, I search for broken links and still find them:

find . -type l | xargs file | grep broken 

What am I doing wrong?

Best Answer

The first problem is that your find command will only find links that used full paths, not relative ones. To illustrate:

$ ln -s /home/terdon/foo/NonExistantFile foo
$ ln -s NonExistantFile bar

$ tree
.
|-- bar -> NonExistantFile
`-- foo -> /home/terdon/foo/NonExistantFile

In the example above, I created two broken links. The first used an absolute path and the second, a relative one. If I now try your find command (having it echo the relinking command instead of running it so we can see what it's doing), only one of the two will be found:

$ find . -lname '/home/terdon/*' -exec \
    sh -c 'echo ln -snf "/home$(readlink "$0")" "$0"' {} \; 
ln -snf /home/home/terdon/foo/NonExistantFile ./foo

The second issue is that your path is wrong. You are recreating links as "/home$(readlink "$0")" "$0". The readlink command will already show the full path so adding /home to it results in /home/home/... which is not what you want.

More importantly, what you are attempting is not possible. If a link is broken, that means that its target does not exist. Since the target doesn't exist, you can't simply relink the file, there's nowhere to link it to. The only thing you could do is recreate the link's target. This, however, is unlikely to be very useful since it would simply make your broken links point to new, empty files. If that is indeed what you want to do, you could try

 find . -type l -exec sh -c 'touch "$(readlink "{}")" ' \; 

Finally, you might want to create a more complex script that i) finds all broken links ii) searches your machine for files with the same name as the target of the link iii) presents you with a list of them and iv) asks you which one it should now link to.

Related Question