May 12 2010

A modest attempt to de-dumb scp

The title of this post isn't entirely fair; scp is an awesome utility, and is probably one of my top 10 typed commands in a given day. (Sadly true, I shuffle files around a lot). Because of how often I use it, however, I do have some long standing issues that have always striked me as just plain silly behavior.

Flag Consistency

scp strives to be consistent with its insecure predecessor, rcp, just like ssh shares many of the same flags as rsh. rcp has been around since 1982, and was largely obsoleted when ssh and friends became available in 1995. Trying to share flags with the original program you're replacing is a noble idea. Unfortunately, there is a single flag that is in conflict between ssh and rcp -- -p.

Because scp uses all the same connection rules (user, password, keypair) as ssh, I think it makes more sense to be consistent with ssh -- not rcp, which as of this writing, has been obsoleted for 15 years. As an end user, I shouldn't have to remember that ssh needs a -p to set a remote port, and scp needs a -P. Since ssh doesn't actually use -P for anything, that's where the original rcp "preserve modes" should land.

Copying local files

scp is for copying files across a network. I don't want it to ever make local copies. If I want a local copy, I'll use cp, thank you very much. How many times have you accidentally omitted the trailing colon on a remote destination, just to end up with a user+host named local copy?

$ touch testfile
$ scp testfile mahlon@martini.nu
$ ls -l mahlon\@martini.nu
-rw-r--r--  1 mahlon  users  0 May 12 07:33 mahlon@martini.nu
$ rm mahlon\@martini.nu

When would you -ever- want that behavior, and want to use scp to do it? Never, I say! Here's what I think is an improvement:

$ touch testfile
$ scp testfile mahlon@martini.nu
Cowardly refusing to make a local copy of 'testfile'.
$ ^D

Local file validity

Another one when copying local files to remote destinations. scp currently goes through all the work of connecting to the remote host before bothering to check if the local file you're trying to copy even is available.

$ scp -v doesnt_exist mahlon@martini.nu:
debug1: Reading configuration data /etc/ssh/ssh_config
debug1: Connecting to martini.nu [] port 22.
debug1: Connection established.
debug1: [...]
debug1: Found key in /home/mahlon/.ssh/known_hosts:5
debug1: Authentications that can continue: publickey,keyboard-interactive
debug1: Next authentication method: publickey
debug1: Offering public key: /home/mahlon/.ssh/id_dsa
debug1: Server accepts key: pkalg ssh-dss blen 433
debug1: Authentication succeeded (publickey).
debug1: channel 0: new [client-session]
debug1: Entering interactive session.
debug1: Sending command: scp -v -t .
doesnt_exist: No such file or directory
debug1: Transferred: stdin 0, stdout 0, stderr 0 bytes in 0.0 seconds
debug1: Bytes per second: stdin 0.0, stdout 0.0, stderr 0.0
debug1: Exit status 1

Why bother?

$ scp -v doesnt_exist mahlon@martini.nu:
doesnt_exist: No such file or directory

Rather than helplessly complain about this stuff into the internet abyss, I went ahead and made a quick patch. You get get it here, if you're so inclined.