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?

  • 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, 2012 at 15:01
  • I tried using -exec but couldn't get it to work all in 'one' line.
    – trusktr
    Apr 27, 2012 at 23:35

5 Answers 5


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.


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.


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

find and ln are good.
readlink is also good.


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

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .