0

This question already has an answer here:

I have a directory which contains many symlinks which point to other directories. Now I would like to rename a common ancestral directory of the linked directories by the symlinks, and also have symlinks pointing to the same directories except with renamed pathnames. For example, the symlinks point to /home/Tim/dir1, /home/Tim/dir2, ..., and now I would like the symlinks point to /data/Tim/dir1, /data/Tim/dir2, ....

I would like to automate the process of update the symlinks. But there are several questions:

  1. I heard that symlinks can't be edited. So do I have to create new symlinks and then overwrite the existing ones?

  2. how can I get the pathname of the directory pointed to by a symlink, and then use some text processing programs to replace the old name of the ancestral directory in the pathnames with its new name, and create a symlink pointing to the directory with a new pathname? Thanks.

marked as duplicate by Anthon, Networker, derobert, chaos, jimmij Mar 4 '15 at 12:26

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

3

I heard that symlinks can't be edited. So do I have to create new symlinks and then overwrite the existing ones?

Symlinks can't be edited, that is correct. You can replace symlinks to files in a single operation with the -f option to ln, and if you add -T you can process symlinks to directories in the same way:

ln -sfT /data/Tim/dir1 symlink1

will create symlink1 pointing to /data/Tim/dir1, replacing any existing symlink (or file!) named symlink1.

how can I get the pathname of the directory pointed to by a symlink, and then use some text processing programs to replace the old name of the ancestral directory in the pathnames with its new name, and create a symlink pointing to the directory with a new pathname?

realpath will give you the absolute path to which the symlink points. To process your symlinks:

for symlink in *; do
    if [ -L "${symlink}" ]; then
        origpath="$(realpath "${symlink}")" && ln -sfT "${origpath/home/data}" "${symlink}"
    fi
done

This retrieves the path of each file in the current directory (so I'm assuming all symlinks in the current directory need fixing) and relinks it, replacing the first occurrence of home with data. Using && ensures that the symlink is only replaced if realpath succeeded (it fails if the target doesn't exist).

  • Thanks. Why does "${origpath/home/data}" replace home with data in the value of origpath`? Is this a bash feature, named something? – Tim Mar 9 '15 at 22:20
  • The Advanced Bash Scripting Guide refers to it as "substring replacement"; it's a feature provided by bash and zsh at least. – Stephen Kitt Mar 9 '15 at 22:25

Not the answer you're looking for? Browse other questions tagged or ask your own question.