I want to copy local file to a remote server using scp.

scp -rp local-file my.server.com:/tmp/

Sometimes I forget to specify where on the remote server the file should be copied to:

scp -rp local-file my.server.com

or, other times I mistype : for an ;:

scp -rp local-file my.server.com;/tmp/

in both cases, scp should fail. But instead, it behaves completely idiotically, and copies the local file locally, as cp would do.

cp local-file my.server.com

Even man scp says that scp is remote file copy program. So why is it failing silently, and behaving like cp ?

Any way to fix this ?

My version of openssh-client is 1:6.0p1-4+deb7u6

  • 7
    There is nothing to "fix", the behavior is as expected, and can useful when scripting. That being said: superuser.com/questions/141986/…
    – Mat
    Jul 25 '17 at 11:59
  • 7
    You wouldn't manually. You would when writing generic scripts (e.g. deployment on clusters where what goes where (or is taken from where) varies depending on the "environment" - simple test setup with a single system versus prod deployment with lots of different machines.). Just because you don't find a feature useful doesn't mean everyone else agrees.
    – Mat
    Jul 25 '17 at 12:50
  • 12
    There is no failure. It doesn't match your expectations, that's a different issue. SCP does one thing: copy a source to destination.
    – Mat
    Jul 25 '17 at 12:55
  • 1
    @MartinVegter scp's "one thing" is copying between hosts on a network. The current machine is a part of the network. Would you also consider scp performing local->remote, remote->local, and remote->remote copies (rather than a separate program being required for each) to violate the "do one thing" philosophy?
    – Chris H
    Jul 25 '17 at 14:24
  • 1
    @MartinVegter why can scp also cp? for the same reason that rsync can sync from local to local, local to remote, remote to local, and remote to remote. rsync's a generic tool that syncs data from one location to another. scp is a generic tool that copies data from one location to another. both can work with both local & remote sources and destinations.
    – cas
    Jul 25 '17 at 14:47

In bash, you could write a wrapper function like this.

function scp { 
  if grep -q ':[^ $]' <<< "$*" ; then
    command "${FUNCNAME[0]}" "$@"
    echo "missing or invalid hostname:path in scp command"
    return 1

This is a very crude example, all it does is check that there's a : followed by at least one non-space character in the command line (that's good enough for a proof-of-concept example, but inadequate for real-world use). If there is, it runs the scp command. If not, it prints an error message and returns with exit code 1.

Or you could write it as a script - it makes little difference either way.

BTW, I said "In bash" above, that's because I've only tested the above function in bash. It's not meant to imply that only bash can do this. Most other sh implementations allow you to do the same or similar. The syntax may vary slightly, and you may have to hard-code command scp ... rather than the more generic command "${FUNCNAME[0]} ...".

PS: I make no judgement on whether scp is "supposed to" behave like this or not. That's for you to decide on your own system. However, becoming dependant on stuff like this puts you at a severe disadvantage when you have to work on system without all your custom hacks/crutches.


short answer is you can't.

note that man scp mention remote host as optional:

scp (scp options removed) [[user@]host1:]file1 ... [[user@]host2:]file2

now, when you issue the command

scp arg1 arg2

scp will decide where is remote host by looking for : in arg1 or arg2 (and two remote host may be permited (solaris, ubuntu) altough that was not always the case).

If neither arg1, nor arg2 have colon, scp simply behave as cp.


Further to other answers, note that scp is not a separate protocol per se, but is simply the older rcp using ssh for transport rather than unencrypted TCP. It was intended as a drop-in replacement where any scripted or non-scripted rcp could be replaced by the more secure scp without any changes. And rcp allowed either remote or local copying by parsing the :.


Why not try sftp ? You can cd on the remote server, and lcd on local file system, then put to uploade a local file to remote.


Although it's called a remote file copy program, I think it's designed to be able to fulfill local copying needs alongside remote needs. This behaviour was mirrored in my environment when testing.

Also worth noting that when retrieving the value from the environment variable $? after running it locally, a return code of 0 was observed. This indicates that it behaved as expected, and did not output an error code.

I'm not sure that a way around this default behaviour exists unfortunately. Using another tool may be the only other option.

  • what's wrong with using cp to "fulfill our local copying needs" ? Jul 25 '17 at 13:25
  • 2
    @MartinVegter: Then you have to write lots of code that basically says "if <destination> is on local machine <perform copy with cp> else <perform copy with scp>". Much simpler if you can just do everything with scp. And it keeps scp simpler too - it doesn't have to check for a special case.
    – psmears
    Jul 25 '17 at 14:41
  • @MartinVegter Nothing whatsoever. I personally use cp for local copies too. I'd imagine it probably exists for the convenience of having both functions included within one tool.
    – Hugh
    Jul 26 '17 at 9:27

Not the answer you're looking for? Browse other questions tagged or ask your own question.