How to convert symlink to regular file?

LinuxSymlink

Linux 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.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionnibotView Question on Stackoverflow
Solution 1 - LinuxnibotView Answer on Stackoverflow
Solution 2 - LinuxYadhuView Answer on Stackoverflow
Solution 3 - LinuxkbrockView Answer on Stackoverflow
Solution 4 - LinuxdscloseView Answer on Stackoverflow
Solution 5 - LinuxPaul BeusterienView Answer on Stackoverflow
Solution 6 - LinuxAndrii RadykView Answer on Stackoverflow
Solution 7 - Linuxuser6411287View Answer on Stackoverflow
Solution 8 - LinuxTrevor HickeyView Answer on Stackoverflow
Solution 9 - LinuxBANZ1111View Answer on Stackoverflow
Solution 10 - Linuxuser12702261View Answer on Stackoverflow
Solution 11 - LinuxBrian CainView Answer on Stackoverflow
Solution 12 - Linuxuser3879068View Answer on Stackoverflow
Solution 13 - LinuxFreddieView Answer on Stackoverflow
Solution 14 - LinuxttwhyView Answer on Stackoverflow