Replace Symbolic Links with Files
Is there an easy way to replace all symbolic links with the file they link to?
For some definitions of "easy":
#!/bin/sh
set -e
for link; do
test -h "$link" || continue
dir=$(dirname "$link")
reltarget=$(readlink "$link")
case $reltarget in
/*) abstarget=$reltarget;;
*) abstarget=$dir/$reltarget;;
esac
rm -fv "$link"
cp -afv "$abstarget" "$link" || {
# on failure, restore the symlink
rm -rfv "$link"
ln -sfv "$reltarget" "$link"
}
done
Run this script with link names as arguments, e.g. through find . -type l -exec /path/tos/script {} +
If i understood you correctly the -L
flag of the cp
command should do exactly what you want.
Just copy all the symlinks and it will replace them with the files they point to.
cp -L files tmp/ && rm files && mv tmp/files .
Might be easier to just use tar to copy the data to a new directory.
-H (c and r mode only) Symbolic links named on the command line will be followed; the target of the link will be archived, not the link itself.
You could use something like this
tar -hcf - sourcedir | tar -xf - -C newdir
tar --help:
-H, --format=FORMAT create archive of the given format
-h, --dereference follow symlinks; archive and dump the files they point to
"easy" will be a function of you, most likely.
I'd probably write a script that uses the "find" command line utility to find symbolically linked files, then calls rm and cp to remove and replace the file. You'd probably do well to also have the action called by find check that there's enough free space left before moving the sym link too.
Another solution may be to mount the file system in question through something that hides the sym links (like samba), then just copy everything out of that. But in many cases, something like that would introduce other problems.
A more direct answer to your question is probably "yes".
Edit: As per the request for more specific info. According to the man page for find, this command will list all sym link files in to a depth of 2 directories, from /:
find / -maxdepth 2 -type l -print
(this was found here)
To get find to execute something on finding it:
find / -maxdepth 2 -type l -exec ./ReplaceSymLink.sh {} \;
I believe that'll call some script I just made up, and pass in the file name you just found. Alternatively, you could capture the find output to file (use "find [blah] > symlinks.data", etc) then pass that file in to a script you've written to handle copying over the original gracefully.