For example, I'm renaming many files inside a tree like this:

[bash]$ for file in `find . -name "*gsf*"`; do `mv $file ${file/gsf/msf}`; done

That renames all the instances of "gsf" in file names matching gsf to "msf", but softlinks continue to point to now-non-existent files containing "gsf".

For example, this is what happens after the rename:

lrwxrwxrwx 1 trusktr users     20 Apr 25 14:39 libmsf-1.so -> libgsf-1.so.114.0.23
lrwxrwxrwx 1 trusktr users     20 Apr 25 14:39 libmsf-1.so.114 -> libgsf-1.so.114.0.23
-rwxr-xr-x 1 trusktr users 265584 Apr 21 04:41 libmsf-1.so.114.0.23

As you can see, the soft links point to libgsf-1.so.114.0.23 which doesn't exist anymore because it was renamed to libmsf-1.so.114.0.23.

What can I do so that the rename also happens to the soft link pointers?

migrated from stackoverflow.com Apr 27 '12 at 14:54

This question came from our site for professional and enthusiast programmers.

  • Off topic: I wonder if it wouldn't be more efficient to simply use -exec option of file, instead of the loop. – rahmu Apr 27 '12 at 15:01
  • I tried using -exec but couldn't get it to work all in 'one' line. – trusktr Apr 27 '12 at 23:35

Nothing; that's what makes them symbolic links, you need to deal with them yourself. Hard links reference the actual index node ("inode") in the filesystem, and will therefore remain valid; this is exactly why you would use hard instead of symbolic links in this case.


Aside from the technical explanation, already answered. You can change where the symbolic links point to:

  1. Find them with find . -type l
  2. Change their target with ln -sfT target link_name

The options -sfT must be specified to repoint symbolic links without surprises.


find and ln are good.
readlink is also good.


Based on @C2H5OH's and @user1277476's answers, I came up with a solution:

$ for file in `find . -type l`; do link=$(readlink $file); ln -sfT ${link//gsf/msf} $file; done

Since I cannot add a comment, here is a version which does not invoke a shell for finding links, thus preventing additional overhead due to fork() and other syscalls

for file in $(find . -type l); do 
    link=$(readlink $file); 
    ln -sfT ${link//gsf/msf} $file; 

This is based on @trusktr answer

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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