18

I'm trying to copy all files that do not begin with the letter "a", in ksh.

Copying from the source machine to destination machine is working fine:

scp -p !(a*) user@machine:/path/directory/.

But, if I am on the destination server and want to copy from the source server, is failing:

scp -p user@machine:/path/!(a*) .

Any ideas?

26

I agree with vonbrand. Globing is handled by the shell you're running in. So scp user@machine:/path/* will expand /path/* to the files in the LOCAL /path/*, not on the remote machine.

However, just for grins I tried:

scp "user@machine:/path/[regex here]" .  

and .... it worked. Try that. Note the quotes. Very necessary. Let us know.

Note: the user account on the remote machine may default to a different shell program than yours, so the rules of wild card expansion may be different, so 'ware that.

1
  • Saved my time. Thanks a lot. – therealak12 Aug 2 '20 at 18:14
1

This isn't "scp with regular expressions", the one handling the file globs is the shell. scp just gets handed the already expanded list of files. And the expansion happens on the machine where the command is run.

Sorry, can't (easily) do.

1
  • 1
    This answer is wrong. Please remove :) – Michael Jan 20 '17 at 20:33
1

What I found was that on older HP-UX machines (parisc 11.11), I had to use [^a]* But, on newer machines (parisc 11.31 and newer) it works with !(a*)

This is what I ended up with. And it works:

    if [[  ${S_MACH} = "phd026a" || ${S_MACH} = "tht030a" ]]
    then
            scp -p -r ${S_MACH}:${S_DIR}/bin/[^a^b^c^p]* ${D_DIR}/bin/.
    else
            scp -p -r ${S_MACH}:${S_DIR}/bin/!((a*)|(b*)|(c*)|(p*)) ${D_DIR}/bin/.
    fi
1
  • Both solutions work for me on an 11.11 server. – user14755 Sep 30 '15 at 0:03
0

Remote names passed to scp are actually interpreted as a whitespace-separated list of patterns on the remote side. This is often an annoyance when you try to copy a file whose name contains spaces, but here it's useful: scp -p 'user@machine:/path/a*' . would copy all files whose name begins with a.

Your command will work if you quote the pattern so that it's interpreted remotely rather than locally, provided you pass another hurdle. The pattern !(a*) is not a basic shell pattern, it's a ksh extension (that bash and zsh also support if you set the appropriate option). So this will only work if your remote shell is ksh, not if it's some other shell and you exec ksh from .profile or something similar.

The easy way, unless you're in some kind of restricted or antique environment, is to forget about scp. You'd like remote files to work just like local files, so make them local files: mount the remote directory with sshfs. This requires FUSE on the local machine and an SFTP server (i.e. an sftp-server executable that sshd launches) on the remote machine.

mkdir ~/net/machine
sshfs user@machine:/ ~/net/machine
cp -p ~/net/machine/path/!(a*) .

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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