How to convert symlink to regular file?
LinuxSymlinkLinux Problem Overview
What is the most direct way to convert a symlink into a regular file (i.e. a copy of the symlink target)?
Suppose filename
is a symlink to target
. The obvious procedure to turn it into a copy is:
cp filename filename-backup
rm filename
mv filename-backup filename
Is there a more direct way (i.e. a single command)?
Linux Solutions
Solution 1 - Linux
There is no single command to convert a symlink to a regular file. The most direct way is to use readlink
to find the file a symlink points to, and then copy that file over the symlink:
cp --remove-destination `readlink bar.pdf` bar.pdf
Of course, if bar.pdf
is, in fact, a regular file to begin with, then this will clobber the file. Some sanity checking would therefore be advisable.
Solution 2 - Linux
for f in $(find -type l);do cp --remove-destination $(readlink $f) $f;done;
- Check symlinks in the current directory and subdirectories
find -type l
- Get the linked file path
readlink $f
- Remove symlink and copy the file
cp --remove-destination $(readlink $f) $f
Solution 3 - Linux
Just a rehash of other's answers, but adding the "sanity check" to ensure the link passed in is actually a symbolic link:
removelink() {
[ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"
}
This is saying that if the file is a symbolic link, then run the copy command.
Solution 4 - Linux
For text files the sed
command can do this in one line if you pass it the in-place switch (-i
). This is because sed
does a single pass over a file, cats the output into a temporary file which it subsequently renames to match the original.
Just do an inline sed
with no transforms:
sed -i ';' /path/to/symbolic/link
Solution 5 - Linux
On OSX
> rsync `readlink bar.pdf` bar.pdf
Solution 6 - Linux
cp can remove the destination file:
cp --remove-destination target filename
Solution 7 - Linux
This solution works with symlink files and symlink folders/subfolders.
One line, no script needed. This would be ideal to export or transfer symlinks elsewhere.
Put everything inside a folder.
rsync --archive --copy-links --recursive folderContainingSymlinkFilesAndSymlinkFoldersAndSubfolders myNewFolder
Solution 8 - Linux
Many have already stated the following solution:
cp --remove-destination `readlink file` file
However, this will not work on symbolically linked directories.
Adding a recursive and force will not work either:
cp -rf --remove-destination `readlink file` file
cp: cannot copy a directory, ‘path/file, into itself, ‘file’
Therefore, it is probably safer to delete the symlink entirely first:
resolve-symbolic-link() {
if [ -L $1 ]; then
temp="$(readlink "$1")";
rm -rf "$1";
cp -rf "$temp" "$1";
fi
}
Not exactly a one-liner like you had hoped, but put this it into your shell environment, and it can be.
Solution 9 - Linux
Another approach if you find yourself doing this often is adapting kbrock's answer into a shell script and putting it into /usr/bin/. Something along the lines of:
if [ $# -ne 1 ]
then
echo "Usage: $0 filename"
exit 1
fi
[ -L "$1" ] && cp --remove-destination "$(readlink "$1")" "$1"
chmod +x it, and then just run it as a normal command.
Solution 10 - Linux
Change all file.txt from link into file.
for f in *.txt; do echo $(readlink $f) $f | awk '{print "rsync -L "$1" "$2}'; done | bash
Solution 11 - Linux
There's no single command. But if you don't want a copy and all you want is another reference, you can replace the symlink with a link (aka "hard link"). This only works if they're on the same partition, BTW.
rm filename
ln target filename
Solution 12 - Linux
Rsync can nativly deference the symlink for you using -L flag.
[user@workstation ~]$ rsync -h | grep -- -L
-L, --copy-links transform symlink into referent file/dir
It would be as simple as: rsync -L <symlink> <destination>
Solution 13 - Linux
This worked perfectly for me (edited to work with spaces):
find . -type l | while read f; do /bin/cp -rf --remove-destination -f $(find . -name $(readlink "${f}")) "${f}";done;
Allows you to recursively convert all symlinks under the current working folder to its regular file. Also doesn't ask you to overwrite. the "/bin/cp" exists so that you can bypass a possible cp -i alias on your OS which prevents the "-rf" from working.
Solution 14 - Linux
in case of "relative" symlinks you could add a awk statement to @jared answer:
for f in $(find . -type l); do /bin/cp -rf --remove-destination -f $(find . \! -type l -name $(readlink $f | awk -F"../" '{print $NF}')) $f;done;
If you have symlinks pointing to directories you need to use a more radical approach because cp --remove-destination does not work together with symlinks directories correctly
for f in `find . -type l`; do (cd `dirname $f`; target=`basename $f`; source=`readlink $target` ; rm -rf $target && cp -r $source $target); done
For sure this could be written with less overhead. but it is quite good to read in my opinion.