242

Why can't I copy with scp when I'm using * characters in the path?

scp SERVERNAME:/DIR/* .

What configuration does SCP need in order to allow * in the path?

UPDATE: the problem is not on server side; pscp is trying to use SCPv1, and that's why the error message:

scp commandline and error message regarding a file called *

Jeff Schaller
  • 67,283
  • 35
  • 116
  • 255
LanceBaynes
  • 40,135
  • 97
  • 255
  • 351

5 Answers5

240

You need to pass a literal escape to scp to avoid the remote machine treating * as a glob (notice that it is doubly quoted):

scp 'SERVERNAME:/DIR/\*' .
Chris Down
  • 125,559
  • 25
  • 270
  • 266
  • 96
    You either need quotes, or a backslash before the star, not both. And scp is not the one expanding it, the shell is. – phemmer Dec 23 '11 at 04:39
  • 1
    @Patrick That's not correct, scp expands the glob, even if your shell doesn't (you can try it for yourself). There are two stages: stopping your shell from expanding the glob (which is not necessary because it should have nothing to expand the glob to, and thus will remain intact), and telling scp that this character is not a glob. If it was your shell expanding the glob you would not have to escape it at all. – Chris Down Dec 23 '11 at 13:29
  • Er, rather, the shell on the other end expands the glob, not scp. – Chris Down Dec 06 '13 at 17:44
  • 3
    Have you tried it? I just did, works exactly as I described (quoting and escaping causes failure). User1274964 even confirms the behavior in his answer. touch /tmp/abcd.1234; scp 'localhost:/tmp/abcd.\*' ./: scp: /tmp/abcd.*: No such file or directory – phemmer Dec 07 '13 at 01:00
  • 2
    @Patrick The question is about using a literal asterisk, ie, avoiding globbing altogether, not about how to glob on the remote. – Chris Down Dec 08 '13 at 20:57
  • 4
    Actually the question is about getting pscp on the client side to allow remote globbing. – phemmer Dec 08 '13 at 22:08
  • That's not how I interpret the question, but if that's what you want, then you only need one level of quotes. – Chris Down Dec 08 '13 at 23:13
  • @ChrisDown Patrick is right, the backslash is causing the star to be treating as a normal character and cause failure. i had to remove it – vdegenne Jan 12 '17 at 12:42
  • If you want a literal asterisk you need both quotes and the backslash. If you just want globbing on the remote side, use only one of them. – Steen Schütt Aug 17 '17 at 08:50
  • 1
    Yep you do not need to escape the asterisk if you're using the single quotes – arled Oct 23 '18 at 15:22
  • 1
    @Led As already discussed in this comment thread, it depends on what you're trying to do. If your intention is to get a literal asterisk on the remote, then you need both. If your intention is to glob on the remote, then you need only one. If your intention is to glob on the local, then you need neeither. Judging by the initial question, it's not possible to know if OP wants option #1 or #2. – Chris Down Oct 29 '18 at 11:00
  • For me it worked by expanding with double quotes – aerijman Aug 21 '23 at 22:25
100

I found Patrick's advice to be correct, although Chris's answer got me on the right track. Use quotes and then you don't need the backslash before the asterisk.

  • With quotes+backslash:

    $ scp 'SERVERNAME:/tmp/file_num\*' .
    
    scp: /tmp/file_num*.csv: No such file or directory
    
  • With quotes only:

    $ scp 'SERVERNAME:/tmp/file_num*' .
    
    judgments_for_job_171642.csv 100%   32KB  32.0KB/s   00:00    
    judgments_for_job_172394.csv 100%  548KB 182.6KB/s   00:03  
    
AdminBee
  • 22,803
user1274964
  • 1,101
  • 1
  • 7
  • 2
  • 4
    Right, because this means that you want to glob on the remote. The question is about how to stop globbing on the remote (to get a literal *), not about how to glob on the remote only. – Chris Down Dec 08 '13 at 20:57
  • 6
    @ChrisDown. No. The user wants the wildcard not expanded on the host, and does want it expanded on the remote, to allow it to match multiple files there. None of the files returned have a literal '*' in them. Did you mean "stop globbing on the host "? – Tim Bird Sep 07 '16 at 19:38
7

In order to avoid globbing you want both - single quotes and an escaped asterisk:

scp 'SERVERNAME:/DIR/\*' ./

If you want to use wildcards use either single quotes or escape only the asterisk:

scp 'SERVERNAME:/DIR/*' ./
# or
scp SERVERNAME:/DIR/\* ./

It seems that scp only supports wildcards for file names but not for directory names.

1

NOTE: Solution offered below tested and known to work correctly.

Single quotes will break variable expansion if you've aliased part of the path that you're globbing.

Here's a script that uses DOUBLE quotes for the use-case of the globbed filename command-configure_.tar.gz* using a path aliased with a variable:

#!/bin/bash

USEREXECUTINGSCRIPT='admin'
SCRIPTSDIR="myscripts"

SCPUSER='terrencehoulahan'
SCPUSERPASSWD='Change-Me'
SCPHOST='1.2.3.4'
SCPDIRECTORYREMOTE='/Users/terrencehoulahan/Downloads/Ubuntu/18.04'

## Uncomment appropriate below command for your distro to install "sshpass"
#apt-get -y sshpass
#yum -y install sshpass

sshpass -p "$SCPUSERPASSWD" scp -o StrictHostKeyChecking=no $SCPUSER@$SCPHOST:"$SCPDIRECTORYREMOTE/command-configure_*.tar.gz" $(getent passwd|grep ^$(echo $USEREXECUTINGSCRIPT)|cut -d ':' -f6)/$SCRIPTSDIR/

After the closing double quote, the local directory target is constructed by just extracting the specified user's home dir from /etc/passwd.

The scp command itself is prefaced with sshpass and -o StrictHostKeyChecking=no to fully automate the scp command without user interaction. Looks convoluted but better than hard-coding paths which are expected to change from time to time.

Anyhoo, an example using double quotes where variables in the path you're globbing need to be allowed to expand. HTH

F1Linux
  • 2,476
0

Well actually just use -r in similar cases. Especially if you use variables in your script.

Example:

SERVERNAME="root@example.com"

scp -r $SERVERNAME:/DIR/ ./

Nux
  • 1,058
  • 1
  • 11
  • 13