Using scp -v
shows some details about how scp works:
debug1: Sending command: scp -v -t /tmp/A$2.class
Sending file modes: C0644 0 A$2.class
Sink: C0644 0 A$2.class
A$2.class 100% 0 0.0KB/s 00:00
Essentially, since scp runs over ssh, it needs a shell to execute your command, and since the $
is not escaped, the remote shell interprets $2
as an empty string, which makes the target name A.class
.
There are two ways you could go about fixing this. First, you could just use the *
glob in your scp command directly:
scp * foo@bar:/tmp/
But I'm pretty sure you have some other need to use a loop, so here's how to fix it in the loop:
for i in *; do
scp "${i}" "foo@bar:'/tmp/${i}'"
done
Checking the output of scp -v
now shows:
debug1: Sending command: scp -v -t '/tmp/A$2.class'
Success! The single quotes will prevent the remote shell from performing variable expansion.
UPDATE:
Since the argument is interpreted by the shell as an argument, you can do things like this:
scp foo@bar:'$(which ssh)' .
Or even more complicated shell pipelines that result in a filename. This is not a security issue, since if you can connect with scp, you can connect with ssh. But it might make things more convenient for someone.