Convert symlinks to hard links
I'd like to recursively convert soft links to hard links in a directory. I've tried something like this:
for f in *; do (mv $f{,~} && ln $(readlink $f~) && rm $f~) done
…but it has two major problems:
- not recursive
- picks up files that are not symbolic links
It would be nice to somehow feed the above line to find -type l
, but i'm not sure how to do that.
Solution 1:
This command should work:
find -type l -exec bash -c 'ln -f "$(readlink -m "$0")" "$0"' {} \;
How it works:
find -type l
finds all links in the current directory.-
-exec bash -c '...' {} \;
invokes bash to execute...
.It passes
{}
– the name of the link that's currently being processed ‐ as an argument, which bash can access as$0
. readlink -m "$0"
returns the absolute path of the symbolic link's destination.ln -f "$(readlink -m "$0")" "$0"
overwrites (-f
) the symbolic link$0
with a hard link to its target.
If the link cannot be converted for some reason, it will remain untouched and ln will print an error message.