How to get scp to copy the file instead of its symlink

I want to scp a file to a server. The file is a symbolic link, and actually what I want to do is copy the source file.

I don’t want to track the source file’s path manually, because it can be replaced.

How do I get the source file’s absolute path so that I can then scp with it?

Asked By: Eonil


Stat will give you this information:

$ stat current
  File: `current' -> `/home/user/releases/build/'
Answered By: polynomial

Try this line:

readlink -f `which command`

If command is in your $PATH variable , otherwise you need to specify the path you know.

Answered By: daisy

Under Linux, readlink reads the contents of a symlink, and readlink -f follows symlinks to symlinks to symlinks, etc., until it finds something that isn’t a symlink.

This isn’t necessary for scp though: scp always follows symlinks (it always copies file content, ignoring metadata except that -p preserves file times and modes when possible).

If you find yourself disappointed by what metadata scp can and can’t preserve, I suggest using rsync. With no option, rsync copies file contents ignoring metadata. The commonly used option -a preserves all garden-variety metadata (times, symbolic links, permissions and ownership), and there are options to preserve exotic metadata like ACLs and hard links.

You can either do

readlink -f `which command`

or you can get something similar in Linux with

stat `which command` | grep File

If you are adding this to a script, inspect the error. If you don’t want to see the error message in the case when the sym link is not there, go with something like

readlink -f "`which command`" 
Answered By: Alexandre Santos

Comparing the use of commands ls, stat, readlink, taking operations on file /etc/localtime as an example:

  • Using ls:
    [flying@lempstacker ~]$ ls /etc/localtime 
    [flying@lempstacker ~]$ ls -l /etc/localtime
    lrwxrwxrwx. 1 root root 35 Aug  2 22:41 /etc/localtime -> ../usr/share/zoneinfo/Asia/Shanghai
  • Using stat
    [flying@lempstacker ~]$ stat /etc/localtime
      File: ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
      Size: 35          Blocks: 0          IO Block: 4096   symbolic link
    Device: fd01h/64769d    Inode: 272202388   Links: 1
    Access: (0777/lrwxrwxrwx)  Uid: (    0/    root)   Gid: (    0/    root)
    Access: 2016-11-23 09:00:59.999887800 +0800
    Modify: 2016-08-02 22:41:26.090389904 +0800
    Change: 2016-08-02 22:41:26.090389904 +0800
     Birth: -
    [flying@lempstacker ~]$ stat -c "%N" /etc/localtime
    ‘/etc/localtime’ -> ‘../usr/share/zoneinfo/Asia/Shanghai’
  • Using readlink
    [flying@lempstacker ~]$ readlink /etc/localtime
    [flying@lempstacker ~]$ readlink -f /etc/localtime

It seems like that command readlink -f is the best fit.

Explanation on the -f parameter

From man readlink:

-f, --canonicalize: canonicalize by following every symlink in every component of the given name recursively; all but the last component must exist

Answered By: Gorgon

I would use realpath <symlink>.

Probably what you call ‘source’ is the ‘target’ file according to the usage of ln: Usage: ln [OPTION]... [-T] TARGET LINK_NAME

Answered By: XavierStuvw

readlink -f 'which java' didn’t work for me.

But this did:

readlink -f $(which java)
Answered By: NonCreature0714

On MAC OX, “-f” parameter doesn’t work, ‘readlink’ works without any parameter.

KZs-MacBook-Pro:bin kz$ readlink -f pip3
readlink: illegal option -- f
usage: readlink [-n] [file ...]

KZs-MacBook-Pro:bin kz$ readlink pip3
Answered By: Xb74Dkjb

The following would give the full path resolving the symlink.

which [symlink] | xargs realpath
Answered By: KSC

For macOS Catalina try –

readlink -n `which command`
Answered By: Manyam Nandeesh Reddy
Categories: Answers Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.