I want to change the symbolic links pointing to the current directory, to a common directory named /pool

current directory a/b common directory a/pool

I followed every I could find and came close with this script.

shift 2
for i
  a=$(readlink "$i") && ln -sf "$(echo $a | sed "s@$from@$to@")" "$i"

before running the script ...

lrwxrwxrwx 1 neysa neysa  18 Jan  4 22:03 xfsm-logout.png -> system-log-out.png
lrwxrwxrwx 1 neysa neysa  17 Jan  4 22:03 zoom-best-fit.png -> zoom-fit-best.png

after running the script ./rename-links . ../pool/

lrwxrwxrwx 1 neysa neysa  25 Jan  4 22:31 xfsm-logout.png -> ../pool/ystem-log-out.png
lrwxrwxrwx 1 neysa neysa  24 Jan  4 22:31 zoom-best-fit.png -> ../pool/oom-fit-best.png

it's working but with one fault, missing the first letter of the target. What am I doing wrong?


. is a regular expression metacharacter in sed, which matches any single character. Because you just insert the $from path into the regular expression directly, the . is there as though you'd written:

sed "s@.@../pool/@"

yourself. That replaces any single character, once, with "../pool/", so it has the effect of deleting the first character and inserting "../pool/" in its place.

If you run the readlink command manually you'll find that ./ is not a part of the link contents — your ls shows the same.

You will at the least need to special-case "." in your script, since it may or may not be present in the link contents. One option is to use readlink -f on both the link and . — which will give you absolute paths to both — but there are simpler options if you only have the single case to deal with.

If you're in bash you can get away without sed at all using basic parameter expansion:

ln -sf "${a/$from/$to}" "$i"

That will replace the expansion of $from with the expansion of $to in $a, with. treated literally (although * and other shell metacharacters are used - really it should be "${a/"$from"/"$to"}" to avoid that). This is a cleaner and simpler way of doing it overall.

  • Since I am working on icon sets I want all the symlinks in different size folders to point to a common directory which will hold icons in svg format. ( earlier it was in PNG format , hence different size folders with symlinks pointing to same directory) to correct every link manually will be tough since I need a simple script to do it – Babu Philip Jan 5 '15 at 6:59
  • just added -f after readlink in the script as Mr.Michael Homer suggested and staying in the links directory issued command as bash ../rename-links /home/***/links/ ../pool/ * and it worked, it just added ../pool/ in front to the symlinks without deleting any character. Thankyou. – Babu Philip Jan 5 '15 at 9:53

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.